JS apply/call/caller/callee/bind使用方法与区别分析

在JavaScript中,apply、call、caller、callee和bind是五种重要的函数调用方式,它们各自有独特的用途和特点,以下是它们的详细使用方法与区别分析:
一、call方法
1、定义:call方法用于调用一个对象的一个方法,以另一个对象替换当前对象(即改变函数内部的this 指向)。
2、参数:
thisObj:可选,将被用作当前对象的对象。
arg1, arg2, ..., argN:可选,将被传递方法参数序列。
3、示例代码:
function Obj() {
this.value = "对象!";
}
var value = "global 变量";
function Fun1() {
console.log(this.value);
}
window.Fun1(); // global 变量
Fun1.call(window); // global 变量
Fun1.call(document.getElementById('myText')); // input text
Fun1.call(new Obj()); // 对象!
4、说明:call方法可以用来代替另一个对象调用一个方法,将一个函数的上下文从初始上下文改变为由thisObj 指定的新对象,如果没有提供thisObj 参数,则全局对象被用作thisObj。
二、apply方法
1、定义:apply方法与call 类似,也用于改变函数执行时的上下文,区别在于apply 的第二个参数是一个参数数组。
2、参数:
thisObj:可选,将被用作当前对象的对象。

argsArray:参数数组。
3、示例代码:
var func = new function() {
this.a = "func";
};
var myfunc = function(x, y) {
var a = "myfunc";
console.log(this.a);
console.log(x + y);
};
myfunc.call(func, "var", " fun"); // "func" "var fun"
myfunc.apply(func, ["var", " fun"]); // "func" "var fun"
4、说明:apply方法可以将一组参数作为一个数组传递给函数,这在处理动态数量的参数时非常有用,当需要将数组的元素作为参数传递给函数时,apply比call 更合适。
三、caller属性
1、定义:caller属性返回一个对函数的引用,即调用了当前函数的函数体。
2、示例代码:
function CallLevel() {
if (CallLevel.caller == null) {
console.log("CallLevel was called from the top level.");
} else {
console.log("CallLevel was called by another function:
" + CallLevel.caller);
}
}
function funCaller() {
CallLevel();
}
CallLevel(); // "CallLevel was called from the top level."
funCaller(); // "CallLevel was called by another function:"
3、说明:caller属性只有在函数执行时才有定义,如果函数是由顶层调用的,那么caller 包含的就是null,如果在字符串上下文中使用caller 属性,那么结果和functionName.toString() 一样,显示的是函数的反编译文本。
四、callee属性
1、定义:callee属性返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文。
2、示例代码:
function calleeDemo() {
console.log(arguments.callee); // [Function: calleeDemo]
}
function calleeLengthDemo(arg1, arg2) {
if (arguments.length === arguments.callee.length) {
alert("验证形参和实参长度正确!");
return;
} else {
console.log("实参长度:" + arguments.length);
console.log("形参长度:" + arguments.callee.length);
}
}
var sum = function(n) {
if (n <= 0) return 1;
else return n + arguments.callee(n 1);
}
console.log(sum(5)); // 15
3、说明:callee属性是arguments 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名函数的递归或者保证函数的封装性,需要注意的是,callee拥有length 属性,这个属性有时用于验证还是比较好的。arguments.length 是实参长度,arguments.callee.length 是形参长度,由此可以判断调用时形参长度是否和实参长度一致。
五、bind方法

1、定义:bind方法创建一个新的函数,当这个新函数被调用时,它的this 值被绑定到bind 的第一个参数。
2、参数:
thisArg:要绑定的this 值。
arg1, arg2, ..., argN:可选,预设给新函数的参数。
3、示例代码:
var first_object = { num: 42 };
var second_object = { num: 24 };
function multiply(mult) {
return this.num * mult;
}
console.log(multiply.bind(first_object)(5)); // returns 42 * 5
console.log(multiply.bind(second_object)(5)); // returns 24 * 5
4、说明:bind方法可以确保函数的this 保持不变,同时允许预先设置部分参数,这样,bind可以确保函数的this 保持不变,同时允许预先设置部分参数,当需要在事件处理程序中保持特定对象的引用时,bind方法特别有用,因为事件处理程序中的this 通常会指向事件源对象,在模块化或面向对象编程中,bind可以帮助创建具有固定上下文的函数副本,这些副本可以在不改变原有函数上下文的情况下被传递或存储。
相关问题与解答
问题1:call和apply的主要区别是什么?
答案:call和apply的主要区别在于参数的传递方式。call接收单独的参数,而apply接收一个参数数组,这意味着在使用apply时,可以将一组参数作为一个数组传递给函数,而在使用call时,需要逐个列出参数。apply的好处是可以直接将当前函数的arguments对象作为其第二个参数传入。
问题2:bind方法的作用是什么?
答案:bind方法的作用是创建一个新的函数,当这个新函数被调用时,它的this值被绑定到bind的第一个参数。bind还可以接受额外的参数,这些参数会被预设为新函数的参数,这样,无论何时调用新函数,都会使用预设的this值和预置的参数,这使得bind非常适合于需要在事件处理程序中保持特定对象的引用或在模块化编程中创建具有固定上下文的函数副本的场景。
小伙伴们,上文介绍了“js apply/call/caller/callee/bind使用方法与区别分析”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。














