call、apply和bind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向。

apply 、 call 、bind 三者第一个参数都是 this 要指向的对象,也就是想指定的上下文;

apply 、 call 、bind 三者都可以利用后续参数传参;

bind 是返回对应 函数,便于稍后调用;apply 、call 则是立即调用 。

对于 apply、call 二者而言,作用完全一样,只是接受 参数 的方式不太一样。call 是把参数按顺序传递进去,而 apply 则是把参数放在数组 里。

1
2
3
4
5
6
7

var func = function(arg1, arg2) {
...
};

func.call(this, arg1, arg2); // 使用 call,参数列表
func.apply(this, [arg1, arg2]) // 使用 apply,参数数组

实际应用中使用场景:

1
2
3
4
5
6
7
8
9
10
var vegetables = ['parsnip', 'potato']
var moreVegs = ['celery', 'beetroot']

// 将第二个数组融合进第一个数组
// 相当于 vegetables.push('celery', 'beetroot')
Array.prototype.push.apply(vegetables, moreVegs)
// 4

console.log(vegetables)
// ['parsnip', 'potato', 'celery', 'beetroot']

注意:当第二个数组(如示例中的 moreVegs )太大时不要使用这个方法来合并数组,因为一个函数能够接受的参数个数是有限制的。不同的引擎有不同的限制,JS核心限制在 65535,有些引擎会抛出异常,有些不抛出异常但丢失多余参数。

bind() 方法。

MDN 的解释是:bind() 方法会创建一个 新函数,称为绑定函数,当调用这个绑定函数时,

绑定函数会以创建它时传入 bind() 方法的第一个参数 作为 this,传入 bind() 方法的 第二个以及以后的参

数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。

1
2
3
4
5
6
7
8
9
10
var bar = function(){
console.log(this.x);
}
var foo = {
x:3
}
bar(); // undefined
var func = bar.bind(foo); //此时this已经指向了foo,但是用bind()方法并不会立即执行,而是创建一个新函数,如果要直接调用的话 可以 bar.bind(foo)()

func(); // 3

注意:多次 bind() 是无效的。更深层次的原因, bind() 的实现,相当于使用函数在内部包了一个 call / apply ,第二次 bind() 相当于再包住第一次 bind() ,故第二次以后的 bind 是无法生效的。

未完待续。。。