一、arguments是什么
函数调用时,执行第一行代码前,创建当前函数的AO,而AO中默认有两个属性,一个是this,一个是arguments。arguments是一个类数组,存放函数的实参
arguments的本质是对象,不是数组:
function test() {
console.log(arguments instanceof Array) // false
console.log(arguments instanceof Object) // true
console.log(Object.prototype.toString.call(arguments)) // [object Arguments]
}
test()
二、arguments的length(实参的个数)
1、length在调用时确定,往arguments中添加值,不会改变length
function test() {
console.log(arguments.length) // 2
arguments[2] = 3
console.log(arguments, arguments.length) // [1, 2, 2: 3, callee: f, ...] 2
}
test(1, 2)
2、不可以通过length截断arguments
function test() {
arguments.length = 1
console.log(arguments, arguments.length) // [1, 1: 2, 2: 3, 3: 4, callee: f, ...] 1
}
test(1, 2, 3, 4)
可以手动改变arguments.length,但是不会对arguments造成实质性的截断
三、arguments和形参、实参之间的映射关系
- 如果形参有对象的实参,那么形参和arguments之间有映射关系,可以相互改变
- 指定的形参如果没有对应的实参,那么形参和arguments之间没有映射关系
- 有映射关系不代表访问同一块内存,只是保持同步变化
function test(a, b, c) {
// a = 10
// b = 20
// c = 30
arguments[0] = 10
arguments[1] = 20
arguments[2] = 30
console.log(a, b, c) // 10 20 undefined
console.log(arguments[0], arguments[1], arguments[2]) // 10 20 30
}
test(1, 2)
形参a、b由于有对应的实参,和arguments之间有映射关系;形参c没有对应的实参,和arguments之间没有映射关系
四、ES6中的arguments
1、如果形参有初始值,那么形参和arguments之间的映射关系就没有了
function test(a = 3, b) {
a = 10
console.log(a, b) // 10 2
console.log(arguments[0], arguments[1]) // 1 2
}
test(1, 2)
总结:形参和arguments之间映射关系需要满足2个条件
- 形参必须要有对应的实参
- 形参没有初始值
2、箭头函数中没有arguments
const test = () => {
console.log(arguments) // Uncaught ReferenceError: arguments is not defined
}
test()
如果需要获取实参,使用剩余运算符(...)获取
const test = (...rest) => {
console.log(rest) // [1, 2, 3]
}
test(1, 2, 3)
五、callee和caller
- callee是当前函数内置对象arguments的属性,指向当前函数
- caller是当前函数的属性。谁调用了当前函数,就返回谁,如果是在a函数中调用了b函数,那么b.caller指向a函数;如果在全局调用了b函数,b.caller指向null。严格模式下使用caller会报错
function parent() {
son(1, 2, 3)
}
function son(a, b) {
console.log(son.caller) // f parent(){}
console.log(son.length) // 形参的个数:2
console.log(arguments.length) // 实参的个数:3
console.log(arguments.callee === son) // true
}
parent()
callee的使用场景:匿名函数调用自己
function recursion() {
return function (n) {
if (n < 1) {
return 1
} else {
return n * arguments.callee(n - 1)
}
}
}
const result = recursion()(5)
console.log(result)