Home  >  Article  >  Web Front-end  >  Array expansion in JavaScript parameters [Translation]_javascript skills

Array expansion in JavaScript parameters [Translation]_javascript skills

WBOY
WBOYOriginal
2016-05-16 17:49:411437browse

Translator’s Note: This article is going to talk about the knowledge points in ECMAScript 6, if you don’t even understand ES5. I have to say, You are already very behind. CSS4, HTML6, and even ES7 ES8 have all started planning, hurry up, otherwise you will be eliminated!

Sometimes, we need to expand an array into multiple elements, and then use these elements as parameters for function calls. You can use Function.prototype.apply in JavaScript to implement this expansion operation , but It cannot be applied when executing a constructor. This article explains what the spreading operation is and how to perform the spreading operation while using the new operator.

1. Spreading

Unpacking means to provide the required parameters through an array in a function call or method call, or when executing a constructor. In Python, this operation is called unpacking . ECMAScript.next already has the (expand operator) spread operator (represented as a prefix ...) to perform this expansion operation. In current JavaScript, you can The same effect is achieved through the Function.prototype.apply method.

Translator's Note: In addition to being used in the position of actual parameters to expand an array, the expansion operator can also be used in the position of formal parameters to represent the remaining parameters. Please see the MDN document I translated Remaining Parameters

2. Expand function parameters

The Math.max() method returns the maximum value from 0 to several numeric type parameters. With the expansion operation symbol, you can directly use an array as a parameter:

Math.max(...[13, 7, 30])
This is equivalent to the following writing

Copy code The code is as follows:

Math.max(13, 7, 30)

In In current JavaScript, you can use apply().
Copy code The code is as follows:

> Math.max.apply(null, [13, 7, 30])
30

The function of the apply method is: use the following calling method:
Copy code The code is as follows:

func.apply(thisValue, [param1, param2, ...])

to replace this
Copy the code The code is as follows:

thisValue.func(param1, param2, ...)

It should be noted that func is not necessarily a method belonging to thisValue. apply can make it temporarily possess this method.

3. Expand the parameters of the constructor

The Date constructor accepts several numerical type parameters and generates a Date object. Through the expansion operator, you can directly pass in an array.
Copy code The code is as follows:

new Date(...[2011, 11, 24]) // Christmas Eve 2011

However, this time we cannot use the apply method to implement the expand operation because it does not work with new:
Copy code The code is as follows:

> new Date.apply(null, [2011, 11, 24])
TypeError: function apply () { [native code] } is not a constructor

The new operator expects Date.apply to be a constructor. Even if you enclose this expression in parentheses, the fundamental problem still exists: apply executes a function call, it cannot pass parameters to the new operator.

3.1 Solution
Step one. Let’s make the result correct first, wait a moment Then consider how to use an array to replace the separated parameters.

Copy the code The code is as follows:

new (Date.bind(null, 2011, 11, 24))

We first use bind() to create a parameterless function (the parameters are already bound inside the bound function), and then call it using new, just like calling a normal constructor. bind function The signature is as follows:
Copy code The code is as follows:

func.bind(thisValue, arg1, arg2 , ...)

bind function converts the original function func into a brand new function. The this value of this brand new function is always the parameter The value specified by thisValue, and its initial parameters include all parameters from arg1 to the end. When this new function is called, the newly added parameters will follow the existing ones bound by bind The parameters are followed by . MDN has more detailed information . Note that in the above example, the first parameter is null, because the Date function does not require a thisValue: When called as a constructor, the new operator will overwrite the thisValue. specified through bind

Step 2.We want to pass the array to bind. So we use apply again to convert an array into expanded parameters and pass them to the bind function.

Copy code The code is as follows:

new (Function.prototype.bind .apply(
Date, [null].concat([2011, 11, 24])))


We call the apply method on the function Function.prototype.bind, with There are two parameters:

•The first parameter: the value of this is specified as Date, which is equivalent to the Date.bind(...) written above.
•The second parameter: The parameters passed to the bind method, null and the following array [2011, 11, 24] are connected to form a new array.

3.2 A library function

Mozilla suggests encapsulating the above work into a library method. The following code is slightly modified based on their suggestion:

Copy code The code is as follows:

if (!Function.prototype.construct) {
Function.prototype.construct = function(argArray) {
if (! Array.isArray(argArray)) {
throw new TypeError("Argument must be an array");
}
var constr = this;
var nullaryFunc = Function.prototype.bind.apply(
constr, [null].concat(argArray));
return new nullaryFunc();
};
}

Run it:
Copy the code The code is as follows:

> Date.construct([2011, 11, 24])
Sat Dec 24 2011 00:00:00 GMT 0100 (CET)

3.3 A seemingly simpler solution
You can manually implement the operation of the new operator. For example:
Copy the code The code is as follows:

var foo = new Foo("abc");

is actually equivalent to:
Copy code The code is as follows:

var foo = Object.create(Foo.prototype);
Foo.call(foo, "abc");

According to this principle, we can write a simple library method:
Copy code The code is as follows:

Function.prototype.construct = function(argArray) {
var constr = this;
var inst = Object.create(constr.prototype);
constr.apply(inst, argArray);
return inst;
};

Alas! Calling Date as an ordinary function is the same as calling it as a constructor: it will ignore the this value specified by the first parameter in the call() and apply() methods, and will always generate and return A new instance.

Translator's Note: The author misunderstood here. Calling Date as a normal function and calling it as a constructor are completely different. Without new, regardless of whether there are parameters or not, Date() will only return the string of the current time, that is (new Date()).toString()
Copy code The code is as follows:

> Date.construct([2011, 11, 24])
{}

Translator’s Note: In the built-in constructor, When calling constructors such as Array(), Function(), RegExp(), and Error(), it is almost the same whether adding new or not. For example, Array(10) also generates an array, but Number(), String(), Boolean () is different. Without adding new, they are type conversion functions, returning the original value. Adding new is a constructor, returning an object value.
Copy Code The code is as follows:

>typeof Number("1")
"number"
>typeof new Number("1")
"object"

As you can see, when operating the Date() method, the construct() method we wrote does not work as expected, and there are some other The built-in constructor also behaves the same as Date. However, if you are operating a custom constructor in a library, this method can basically work normally (a small number of constructors return the object value you specify instead of returning the default value. The automatically generated instance this).

Translator's Note: As long as the return statement of a constructor returns an object value, it will overwrite the default this value. For example:
Copy code The code is as follows:

function Func1(){
  this.value = "this"; return {}
}

function Func2(){
this.value = "this"; return 1}function Func3(){ this.value = "this";}>new Func1() // The returned {} is an object value, covering the default this.{}>new Func2() //The returned 1 is an original value, so the default this.{value: "this"}>new Func3( ) //There is no return statement, and undefined is returned by default, which is a primitive value, so the default this is still returned.{value:"this"}>new Func3 //When there are no parameters, the parentheses can be omitted.{value:"this "}
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn