在JavaScript中,call、apply和bind是Function对象自带的三个方法,都是为了改变函数体内部this的指向。
apply 、 call 、bind三者第一个参数都是this要指向的对象,也就是想指定的上下文;apply 、 call 、bind三者都可以利用后续参数传参;bind 是返回对应函数,便于稍后调用;apply 、call则是立即调用。
下面是例子:
但是如果我们有一个对象banana= {color : 'yellow'},我们不想重新定义 say 方法,那么我们可以通过 call 或 apply 用 apple 的 say 方法:
apple.say.call(banana); //此时的this的指向已经同过call()方法改变了,指向的是banana,this.color就是banana.color='yellow';//结果是My color is yellow apple.say.apply(banana);//同理,此时的this的指向已经同过apply()方法改变了,指向的是banana,this.color就是banana.color;
// 如果传入的是 null: apple.say.apply(null); // null是window下的,此时,this 就指向了window ,但是window下并没有clolr这个属性,因此this.clolr就是window.color=undefined;
2.对于 apply、call 二者而言,作用完全一样,只是接受 参数 的方式不太一样。call 是把参数按顺序传递进去,而 apply 则是把参数放在数组 里。
var array1 = [12,'foo',{name:'Joe'},-2458];
var array2 = ['Doe' , 555 , 100];
Array.prototype.push.call(array1, array2);
// 这里用 call 第二个参数不会把 array2 当成一个数组,而是一个元素
//等价于array1.push(‘‘'Doe' , 555 , 100’’),array1.length=5;
Array.prototype.push.apply(array1, array2);
// 这里用 apply 第二个参数是一个数组
// 等价于: array1.push('Doe' , 555 , 100),array1.length=7;
3.类数组使用数组方法
vardivElements = document.getElementsByTagName('div');
//虽然 divElements 有length属性,但是他是一个伪数组,不能使用数组里面的方法
Array.prototype.slice.call(document.getElementsByTagName('div'));
或者是用Array.from()转化一下;
4.验证一个对象/数组的类型可以用:
Object.prototype.toString.call(obj) ;
5.bind()方法,MDN 的解释是:bind()方法会创建一个 新函数,称为绑定函数,当调用这个绑定函数时,
绑定函数会以创建它时传入bind()方法的第一个参数 作为this,传入bind()方法的 第二个以及以后的参
数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。
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()是无效的,只有第一次生效;
6.apply、call、bind三者相比较,之间又有什么异同呢?何时使用apply、call,何时使用bind呢。简单的一个例子:
var obj = {
x: 81,
};
var foo = {
getX: function() {
return this.x;
}
}
console.log(foo.getX.bind(obj)()); //81返回一个function,需要再次调用;
console.log(foo.getX.call(obj));//81
console.log(foo.getX.apply(obj));//81