本文详细解析 JavaScript 中 call、apply 和 bind 三个方法的原理与区别。三者均用于改变函数执行时的 this 指向,其中 call 和 apply 用于立即执行函数,区别仅在于参数传递形式(列表 vs 数组),而 bind 则返回一个新函数。文章通过代码示例展示了它们在获取数组最值以及将伪数组转换为真数组等实际场景中的应用。
JavaScript 早期的继承机制依赖于 prototype 原型链,随着 ES6 class 语法的引入,开发者现在可以像其他面向对象语言那样,通过类来实现继承。
为了便于理解,可以将其比喻为小时候家里需要将稻谷加工成大米,但家中没有打米机。于是我们将稻谷送到村里的打米房,请店主操作打米机,将稻谷喂入机器,最终就能得到加工好的大米。
call
call 方法允许指定一个 this 值,并依次传入多个参数来调用函数:
function.call(thisArg, arg1, arg2, ...)
当第一个参数为 null 或 undefined 时,可以利用数组展开语法达到类似效果。需要注意的是,此时的 this 可能并非函数内部实际看到的值:在非严格模式下,若指定为 null 或 undefined,它会自动被替换为全局对象,且原始值会被包装。
apply
apply 方法用于调用一个函数,该函数具有指定的 this 值,且参数以数组(或类数组对象)的形式提供:
function.apply(thisArg, [arg1, arg2])
call 和 apply 本质相同,主要区别在于参数传递方式。call 是 apply 的语法糖,它接受一个参数列表,而 apply 则接受一个包含多个参数的数组。
bind
bind 方法会创建一个新的函数。当这个新函数被调用时,其 this 值被固定为 bind 的第一个参数,其余参数则作为新函数的参数供后续调用使用。
function.bind(thisArg[, arg1[, arg2[, ...]]])
这三个方法的第一个参数均用于指定 this 指向的对象。如果该参数缺失、为 undefined 或 null,在非严格模式下默认指向全局 window 对象。
实际应用场景
应用场景一:从数组中找出最大值、最小值
原生 Math.max 和 Math.min 只能接受逗号分隔的参数列表,但在实际业务中,我们通常处理的是数组。可以使用以下方法实现(也可使用扩展运算符 ...):
let arr = [1, 2, 3]
Math.min.apply(null, arr) // 这里第一个null表示不需要绑定this, 但是也不能省略,不能直接将arr给Math, 因为min必须接受两个及以上参数
应用场景二:伪数组转化成真数组
这通常用于处理 DOM 节点列表、具有 length 属性和序号属性的伪数组对象,或者函数的 arguments 参数。
Array.prototype.slice.apply(fakeArray) // slice 省略参数时就是截取出所有元素,此处相当于 Array.prototype.slice.apply(fakeArray, 0, fakeArray.length)
至此,关于 JavaScript 函数 call、apply 和 bind 的原理及作用的详解介绍完毕。如需了解更多相关内容,可搜索本站往期文章或继续浏览后续文章,感谢大家的支持!