Home > Article > Web Front-end > A comprehensive introduction to the JavaScript arguments object
1. What are arguments
Explained on MDN:
arguments is an array-like object. Represents the parameter list passed to a function.
Let’s first use an example to intuitively understand what arguments in JavaScript look like.
function printArgs() { console.log(arguments); } printArgs("A", "a", 0, { foo: "Hello, arguments" });
The execution result is:
["A", "a", 0, Object]
At first glance, the result is an array, but it is not a real array, so arguments is an array-like object (if you want to know the difference between a real array and an array-like object, you can scroll to the end ).
Look again at the content represented by arguments, which represents all the parameters passed into the function when the function is executed. In the above example, it represents the four parameters passed into the printArgs function. You can use arguments[0], arguments[1]... to obtain a single parameter.
2. arguments operation
2.1 arguments length
arguments is an array-like object, which contains a length property. You can use arguments.length to get the number of parameters passed into the function.
function func() { console.log("The number of parameters is " + arguments.length); } func(); func(1, 2); func(1, 2, 3);
The execution result is as follows:
The number of parameters is 0 The number of parameters is 2 The number of parameters is 3
2.2 arguments to array
Usually use the following method to convert arguments into an array:
Array.prototype.slice.call(arguments);
There is also a shorter way of writing:
[].slice.call(arguments);
Here, just simply call The slice method of an empty array is not called from the prototype level of Array.
Why can the above two methods be converted?
First of all, the result obtained by the slice method is an array, and the parameter is arguments. In fact, any object that meets certain conditions can be converted into an array by the slice method. Take an example:
const obj = { 0: "A", 1: "B", length: 2 }; const result = [].slice.call(obj); console.log(Array.isArray(result), result);
The execution result is:
true ["A", "B"]
As can be seen from the above example, the conditions are: 1) The attribute is 0, 1, 2...; 2) It has the length attribute;
In addition, there is a need The important thing to note is that the arguments of the function cannot be leaked or passed out. What does it mean? Look at the following examples of leaking arguments:
// Leaking arguments example1: function getArgs() { return arguments; } // Leaking arguments example2: function getArgs() { const args = [].slice.call(arguments); return args; } // Leaking arguments example3: function getArgs() { const args = arguments; return function() { return args; }; }
The above approach directly leaks the arguments object of the function. The final result is that the V8 engine will skip optimization, resulting in considerable performance loss.
You can do this:
function getArgs() { const args = new Array(arguments.length); for(let i = 0; i < args.length; ++i) { args[i] = arguments[i]; } return args; }
That’s very curious. Every time we use arguments, the first step is usually to convert them into an array. At the same time, improper use of arguments can easily lead to performance losses, so why not design arguments directly? What about array objects?
This needs to be talked about from the beginning of this language. arguments were introduced in the early days of the language, when the Array object had four methods: toString, join, reverse, and sort. The big reason why arguments inherits from Object is that these four methods are not needed. Now, Array has added many powerful methods, such as forEach, map, filter, etc. So why not let arguments re-inherit from Array in the new version? In fact, this was included in the ES5 draft, but for the sake of forward compatibility, it was ultimately rejected by the committee.
2.3 Modify arguments value
In strict mode and non-strict mode, the results of modifying function parameter values are different. Look at the two examples below:
function foo(a) { "use strict"; console.log(a, arguments[0]); a = 10; console.log(a, arguments[0]); arguments[0] = 20; console.log(a, arguments[0]); } foo(1);
Output:
1 1 10 1 10 20
Another example in non-strict mode:
function foo(a) { console.log(a, arguments[0]); a = 10; console.log(a, arguments[0]); arguments[0] = 20; console.log(a, arguments[0]); } foo(1);
The output is:
1 1 10 10 20 20
As can be seen from the above two examples, in strict mode, the function The parameters in are not related to the arguments object, and modifying one value will not change the other value. In non-strict mode, the two will affect each other.
2.4 Passing parameters from one function to another
The following is the recommended practice for passing parameters from one function to another function.
function foo() { bar.apply(this, arguments); } function bar(a, b, c) { // logic }
2.5 arguments and overloading
Overloading is available in many languages, but not in JavaScript. Let’s look at an example first:
function add(num1, num2) { console.log("Method one"); return num1 + num2; } function add(num1, num2, num3) { console.log("Method two"); return num1 + num2 + num3; } add(1, 2); add(1, 2, 3);
The execution result is:
Method two Method two
So, in JavaScript, functions do not make different calls based on different parameters.
Is there no overloading in JavaScript? No, we can use arguments to simulate overloading. Still the above example.
function add(num1, num2, num3) { if (arguments.length === 2) { console.log("Result is " + (num1 + num2)); } else if (arguments.length === 3) { console.log("Result is " + (num1 + num2 + num3)); } } add(1, 2); add(1, 2, 3)
The execution result is as follows:
Result is 3 Result is 6
3. Arguments in ES6
3.1 Expansion operator
Directly to the chestnut:
function func() { console.log(...arguments); } func(1, 2, 3);
The execution result is:
1 2 3
Succinctly speaking, the expansion operator can expand arguments into independent parameters.
3.2 Rest parameter
is still the best example:
function func(firstArg, ...restArgs) { console.log(Array.isArray(restArgs)); console.log(firstArg, restArgs); } func(1, 2, 3);
The execution result is:
true 1 [2, 3]
From the above results, it can be seen that the Rest parameter represents the remaining parameter set except the explicitly specified one, and the type is Array.
3.3 Default parameters
Chestnut:
function func(firstArg = 0, secondArg = 1) { console.log(arguments[0], arguments[1]); console.log(firstArg, secondArg); } func(99);
The execution result is:
99 undefined 99 1
It can be seen that the default parameters have no effect on arguments, and arguments still only represent all the parameters passed in when calling the function.
3.4 arguments to array
Array.from() is a very recommended method, which can convert all array-like objects into arrays.
4. Arrays and array-like objects
Arrays have one basic feature: index. This is something that ordinary objects don’t have.
const obj = { 0: "a", 1: "b" }; const arr = [ "a", "b" ];
We can use obj[0] and arr[0] to get the data we want, but the ways to get the data are really different. obj[0] uses the key-value pair of the object to access data, while arr[0] uses the index of the array. In fact, the only difference between Object and Array is that Object's properties are strings, while Array's indexes are numbers.
Let’s take a look at array-like objects.
伪数组的特性就是长得像数组,包含一组数据以及拥有一个 length 属性,但是没有任何 Array 的方法。再具体的说,length 属性是个非负整数,上限是 JavaScript 中能精确表达的最大数字;另外,类数组对象的 length 值无法自动改变。
如何自己创建一个类数组对象?
function Foo() {} Foo.prototype = Object.create(Array.prototype); const foo = new Foo(); foo.push('A'); console.log(foo, foo.length); console.log("foo is an array? " + Array.isArray(foo));
执行结果是:
["A"] 1 foo is an array? false
也就是说 Foo 的示例拥有 Array 的所有方法,但类型不是 Array。
如果不需要 Array 的所有方法,只需要部分怎么办呢?
function Bar() {} Bar.prototype.push = Array.prototype.push; const bar = new Bar(); bar.push('A'); bar.push('B'); console.log(bar);
执行结果是:
Bar {0: "A", 1: "B", length: 2}
参考:
JavaScript中的数组与伪数组的区别
MDN arguments
Avoid modifying or passing arguments into other functions — it kills optimization
Optimization killers
Why isn't a function's arguments object an array in Javascript?
arguments 对象
Advanced Javascript: Objects, Arrays, and Array-Like objects
JavaScript 特殊对象 Array-Like Objects 详解
What is a good way create a Javascript array-like object?