ECMAScript 函数的参数与大多数其他语言中的函数的参数有所不同。EMCAScript 函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型。也就说,即便你定义的函数只接受两个参数,在调用这个时也不一定要传递两个参数。因为ECMAScript 中的参数在内部是用一个数组来表示的。函数接收到的始终是这个数组,而不关心数组中包含哪些参数。
在函数中,可以通过 arguments 对象来访问这个参数数组,从而获取传递给函数的每一个参数。arguments 对象只是与数组类似,但是并不是 Array 的实例。
function foo () {
console.log('arguments', arguments);
console.log('typeOf(arugments)', typeof(arguments));
}
foo()
foo(1, 2, 3)
执行结果:
arguments {}
typeOf(arugments) object
arguments { '0': 1, '1': 2, '2': 3 }
typeOf(arugments) object
从上面的例子可以看出 ECMAScript 函数的一个重要特点:命名的参数只是提供便利,但不是必须的。
关于 arguments 对象有两个特点:
arguments 对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数个数决定的。
arguments 的值,永远与对应命名参数的值保持同步。
下面的例子,会体现 arguments 的这两个特点。
function foo (a, b) {
console.log(arguments); // { '0': 1 }
console.log(arguments.length) // 1
console.log('a:', a); // 1
console.log('b:', b); // undefined
arguments[0] = 33;
arguments[1] = 222;
console.log(arguments) // { '0': 33, '1': 222 }
console.log(arguments.length) // 1
console.log(a); // 33
console.log(b); // undefined
}
foo(1)
上面的例子修改了 arguments[0]
会自动反映到对应的命名参数。不过这并不是说读取这两个值会访问相同的内存空间,它们的内存空间是独立的,但他们的值会同步。
另外因为只传入了一个参数, arguments[1] 设置的值不会反映到命名参数中,因为 arguments 对象的长度是由传入的参数个数决定的。这个可以通过上面的输出结果,可以看出。
tips:arguments 的值,永远与对应命名参数的值保持同步,是在非严格模式下才成立的。如果实在严格模式下,则 arguments 的改变,是不会影响到参数的值。而参数值的变化,也不会影响到 arguments 的改变。
callee
arguments 这个对象有一个 callee 属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。
tips:callee 在严格模式下不能使用。