最近在面试一些公司,发现考察 JS 基础的公司非常多,有一次问到了 bind、apply 和 call 的区别,当场没答上来。这次就好好来复习一下 bind、apply 和 call 的用法。
这三个方法的共同点在于改变 this 指向,能够把一个对象的方法交给另一个对象来执行,并且 apply 和 call 是立即执行的。
为什么要改变 this 指向呢?比如A对象有一个 say 方法,B对象需要用到这个方法,我们不需要专门为B重新写这个方法,只需要借用A的方法即可。
apply
MDN文档上对其的解释为:
apply() 方法调用一个具有给定 this 值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
fn.apply(obj, [argsArray])
需要注意的是,apply 的调用者必须是函数,第二个参数必须是数组或者类数组,他们会被转换成数组传入 fn,映射到 fn 对应的参数上。这是 apply 和 call 之间很重要的区别。
我们可以使用 apply 来计算一个数组中的最大值:
const numbers = [5, 6, 2, 3, 7]
const max = Math.max.apply(null, numbers);
console.log(max);
// 输出结果: 7
还可以将一个数组中的每一项添加到另一个数组:
let array = ['a', 'b'];
let elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array);
// ["a", "b", 0, 1, 2]
上文有提到类数组,那什么是类数组呢?
一般数组的特征有:
- 可以通过 index 来进行查询,比如
array[0]; - 数组长度属性
length; - 可通过
for循环和forEach方法遍历。
类数组就是和数组有类似特征的对象(你没看错,类数组是个对象),比如下面这个对象:
let array = {
0: 1,
1: 2,
2: 3,
length: 3
};
这个 array 对象可以通过 index 调用,具有 length 属性,同时也可以通过 for循环来遍历。
注意:类数组无法使用 forEach、splice、push 等数组原型链上的方法,毕竟类数组不是真数组。
call
call和apply比较类似,区别在于call方法接受的是参数列表,而apply接受的是一个参数数组。MDN 对 call 的解释为:
call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
fn.call(obj, a, b, ...)
关于 call 需要注意:
- 调用
call的对象和apply一样,必须是个函数; call的第一个参数是一个对象,如果不传,默认为全局对象window;- 第二个参数开始,可以接受任意个参数,每个参数都会映射到相应位置的
fn的参数上; - 如果将所有参数作为数组传入,他们会作为一个整体映射到
fn对应的第一个参数上,之后的参数都为空。
fn.call(obj, 1, 2, 3)
// fn 接收的参数为 1, 2, 3
fn.call(obj, [1,2,3])
// fn 接收的参数实际上是 [1,2,3], undefined, undefined
bind
MDN 对 bind 的解释为:
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
bind 的语法如下:
fn.bind(obj[, arg1[, arg2[, ...]]])
bind 一样能改变函数的 this 指向,不过 bind 的返回值是函数,并且需要稍后调用才能执行。如果 bind 的第一个参数是 null 或者 undefined,this 就指向全局对象 window。
const module = {
x: 12,
getX: function(){
return this.x;
}
}
const unboundGetX = module.getX;
// unboundGetX 为 undefined
const boundGetX = unboundGetX.bind(module)
// boundGetX 为 42
来一个总结
- apply、call和bind都能改变对象执行上下文;
- apply接收参数为数组或类数组,call 接收的是参数列表,bind接收的是函数;
- apply和call是立即执行,bind需要稍后调用才会执行。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!