最近在面试一些公司,发现考察 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介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!