在JavaScript中,call、apply和bind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向。
- apply 、 call 、bind 三者第一个参数都是 this 要指向的对象,也就是想指定的上下文;
- apply 、 call 、bind 三者都可以利用后续参数传参;
- bind 是返回对应 函数,便于稍后调用;apply 、call 则是立即调用 。
案例:
<script>
function fruits(){
}
fruits.prototype = {
color: 'inherit',
say: function(){
console.log('my color is ' + this.color)
}
}
var apple = new fruits; // 此时方法里面的this指的是fruits
apple.say(); // my color is inherit
</script>
1. 如果我们有一个对象 banana= {color : ‘yellow’} ,我们不想重新定义 say 方法,那么我们可以通过 call 或 apply 用 apple 的 say 方法:
banana = {
color: 'yellow'
}
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 ='yellow';
//My color is yellow
// 如果传入的是 null:
apple.say.apply(null); // null是window下的,此时,this 就指向了window ,但是window下并没有clolr这个属性,因此this.clolr就是window.color=undefined;
//My color is 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. 验证一个对象的类型可以用:
function fruits() {
}
var num = 22
var str = 'string'
var obj = new Object()
console.log(Object.prototype.toString.call(fruits)) // [object Function]
console.log(Object.prototype.toString.call(num)) // [object Number]
console.log(Object.prototype.toString.call(str)) // [object String]
console.log(Object.prototype.toString.call(obj)) // [object Object]
4.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