关于arguments的长度
arguments是在普通函数中的参数数组,使用它来访问传入的每个参数值。
arguments是一个伪数组的形式,其长度依据函数调用时传入的参数数目而定,若在函数中没有显示修改这个属性,则这个属性不会随着手动使用下标添加元素而更改。
在一个函数当中, 使用下标访问元素修改arguments数组:
arguments[9] = 1;
console.log("the arguments' length is ", arguments.length);
console.log(arguments);
输出结果为:
the arguments' length is 1
Arguments(1) [0, 9: 1, callee: ƒ, Symbol(Symbol.iterator): ƒ]//这里的Arguments后面的(1)是我自己添加的,chrome在长度为1的时候不会输出
可以看出,是为arguments增加了一个以下标为键的键值对。
若在使用下标修改arguments之前显式的修改length属性的值,后修改的数据的下标若在length范围内,则会增加到”数组“内,反之则依旧会增加一个以下标为键的键值对。
arguments.length = 3;
arguments[1] = 1;
arguments[9] = 1;
console.log("the arguments' length is ", arguments.length);
console.log(arguments);
输出结果为:
the arguments' length is 3
Arguments(3) [0, 1, empty, 9: 1, callee: ƒ, Symbol(Symbol.iterator): ƒ]
如果是正常的一个数组,其length属性值会随着数组的修改而变动:
let arr = [1];
arr[9] = 1;
console.log(arr,arr.length);
输出结果:(10) [1, empty × 8, 1] 10
关于参数之间的同步
在非严格模式下,arguments中的元素会与传入的有名字的参数相互影响、保持同步。
let fn = function (num1, num2, num3) {
console.log("num1=", num1, ",num2=", num2, ",num3=", num3);
console.log("arg[1]=", arguments[0], ",arg[2]=", arguments[1], ",arg[3]=", arguments[2]);
console.log(arguments);
console.log("");
console.log("change num1 to 0...");
console.log("change arg[2] to 1...");
console.log("change arg[3] to 2...");
num1 = 0;
arguments[1] = 1;
arguments[2] = 2;
console.log("");
console.log("num1=", num1, ",num2=", num2, ",num3=", num3);
console.log("arg[1]=", arguments[0], ",arg[2]=", arguments[1], ",arg[3]=", arguments[2]);
console.log(arguments);
}
fn(123,321);
在上述例子当中,我向fn当中传入参数的时候,仅仅传入了两个参数,这两个参数会在有名参数与arguments参数之间相互保持同步。而第三个参数num3,因为没有传入,并没有在有名参数和arguments参数之间同步。
输出结果为:
num1= 123 ,num2= 321 ,num3= undefined
arg[1]= 123 ,arg[2]= 321 ,arg[3]= undefined
Arguments(2) [123, 321, callee: ƒ, Symbol(Symbol.iterator): ƒ]change num1 to 0...
change arg[2] to 1...
change arg[3] to 2...
num1= 0 ,num2= 1 ,num3= undefined
arg[1]= 0 ,arg[2]= 1 ,arg[3]= 2
Arguments(2) [0, 1, 2: 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
同理,我在上面的fn函数当中,显示修改num3的值,其结果也不会被同步到arguments参数中对应下标位置上面去。
总结的来讲:非严格模式下,arguments参数会与传入的有名字的参数保持同步
下面是严格模式下的输出结果,除了增加“use strict”;语句,其他代码不变:
num1= 123 ,num2= 321 ,num3= undefined
arg[1]= 123 ,arg[2]= 321 ,arg[3]= undefined
Arguments(2) [123, 321, callee: (...), Symbol(Symbol.iterator): ƒ]change num1 to 0...
change arg[2] to 1...
change arg[3] to 2...
num1= 0 ,num2= 321 ,num3= undefined
arg[1]= 123 ,arg[2]= 1 ,arg[3]= 2
Arguments(2) [123, 1, 2: 2, callee: (...), Symbol(Symbol.iterator): ƒ]
在严格模式下,有名参数与arguments参数互不影响。
一个小小的疑问
在红宝书上说:
...这并不意味着它们都访问同一个内存地址,它们在内存中还是分开的。
我试着修改了一下上面的函数,把传入的参数改为了两个对象,使用严格模式的情况下,我分别对num1和arguments[1]的value属性进行修改,可是结果居然是同步的,输出如下语句,结果为true。
console.log(arguments[1] === num2);
大概可能说的是这两个变量名在内存中是分开的?只是在传入引用类型之后指向的是同一块地址。