1. caller
函数的 caller 属性返回调用当前函数的函数。
function fun1() {
console.log(fun1.caller);
}
function fun2() {
fun1();
}
fun2();
在上面的代码中,函数 fun1 是在函数 fun2 执行时被调用,所以 fun1.caller 就是 fun2 。
函数的 caller 属性只有在函数被调用的时候才有效。
function fun1() {
console.log("hello world");
}
console.log(fun1.caller);
在上面的代码中,fun1 没有被调用,fun1.caller 返回 null 。
如果函数是由顶层调用的,那么函数的 caller 属性返回 null 。
function fun1() {
console.log(fun1.caller);
}
fun1();
在上面的代码中,函数 fun1 被顶层调用,fun1.caller 的值为 null 。
2. callee
callee 返回正在执行的函数本身的引用, 它是 arguments 的一个属性 。
function fun1() {
console.log(arguments.callee);
}
fun1();
arguments.callee 只有在函数执行时才有效,因为函数的 arguments 属性只有在函数执行的时候才有效。
function fun1() {
console.log(arguments);
console.log(arguments.callee);
}
fun1();
console.log(fun1.arguments);
console.log(fun1.arguments.callee);
在上面的代码中,调用 fun1 的时候,fun1 的 arguments 属性为一个伪数组对象。此时 arguments.callee 返回函数本身 fun1 。
当函数 fun1 执行结束后,函数的 arguments 属性为 null 。所以 arguments.callee 等价于访问 null 的 callee 属性,所以会报错。
arguments.callee 有一个 length 属性,可以用来获得形参的个数。
function fun1(a, b, c, d, e, f, g) {
console.log(arguments.length);
console.log(arguments.callee.length);
}
fun1(1, 2, 3, 4);
我们再来测试一下参数有默认值的情况,如果你没有了解 function.length 获取参数的个数会失真的问题,可以阅览 这篇文章 来了解它
function fun1(a, b, c = 1, d, e, f, g = 2) {
console.log(arguments.length);
console.log(fun1.length);
console.log(arguments.callee.length);
}
fun1("test");
当函数的参数带有默认值的时候,此时 arguments.callee.length 直接报错。
arguments.callee 可以用来递归匿名函数。
let r = (function (n, r) {
return n == 1 ? r : arguments.callee(n - 1, r + n);
})(10, 0);
console.log(r);
3. this与caller
this 是函数运行时,自动生成的一个内部对象,只能在函数内部使用。this指向调用函数的那个对象。
let obj = {
name: "obj",
fun2: function () {
console.log(this);
console.log(obj.fun2.caller);
},
};
function fun1() {
obj.fun2();
}
fun1();
当函数 fun2 执行的时候, this 指向调用函数的对象,就是 obj ,caller 指向函数执行时外层函数的引用,此时就是 fun1 。