写在前面
我们都知道改变this指向有call,apply,bind三种方法。这篇文章就主要讲一讲bind同前面两种的区别和bind方法的一个小案例。
bind的特性
bind可以改变this的指向,但是他不会去执行这个函数,什么意思呢?我们来看代码
- 例1
var futher = function (name){
this.name = name;
},
function son (){
console.log(this);
}
son.bind(futher)
在这个例子里面并不会让son函数执行,这是bind的特性之一。但是son里面的this指向了futher,这是bind的特性之二。
- 例二
var o = {
name: 'andy'
};
function fn(a, b) {
console.log(this);
console.log(a + b);
};
var f = fn.bind(o, 1, 2);
f();
bind会有一个返回值,这个返回值是改变this后返回的新函数。这个例子里面bind首先将fn函数里面的this指向o对象。然后参数1,2传递给了fn函数里面的a和b。然后执行f函数,this打印结果是o对象,a+b结果是3。
小tip:
bind的第三个特性是返回一个新函数,这与第1个特性不执行函数不矛盾,上面的例子我们用f接收了这个新函数再执行才有了结果哦。
bind特性的总结
我们简单总结一下,bind有3个特点。
- 第一函数不执行。
- 第二是bind里面的第一个参数就代表了this。
- 第三个是会返回一个改变了this的新函数。
bind案例实战
案例功能
我们有一组按钮,点击某个按钮后为了防止多次点击使按钮禁用。三秒后再开启按钮。
案例代码
// 4. 我们有一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮
// var btn1 = document.querySelector('button');
// btn1.onclick = function() {
// this.disabled = true; // 这个this 指向的是 btn 这个按钮
// setTimeout(function() {
// btn1.disabled = false; // 此时定时器函数里面的this 指向的是btn
// }, 3000)
// }
在这个例子里,我们通过选择器获取到了按钮,在点击事件发生后执行的函数里面,先通过disabled让button禁用。然后设计一个定时器,我们知道在定时器里面的this指向的是window,所以this.disabled = false会报错滴,于是乎改成了btn1.disabled。但是这样写不够优雅,假如我们的按钮变量名修改了那么计时器里面的操作也要随着更改。那么如何优化呢? 我们可以在定时器外面var that= this;定时器里面函数that.disabled= false.
如何让定时器函数里面的this指向按钮而不是btn呢,我们可以利用call,apply,bind改变this。
利用bind优化案例代码
我们知道改变this前面说了三种关键字,那么用哪种更好呢,毫无疑问bind比较合理。因为bind不仅改变了this而且不会立即调用函数。而是通过定时器去触发这个函数。代码如下
var btns = document.querySelectorAll('button');
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
this.disabled = true;
setTimeout(function() {
this.disabled = false;
}.bind(this), 3000);//这个this指向的是btn对象
}
}
定时器函数里面的this指向的是window,而bind不在定时器函数里面,在btn.onclick函数里面,所以bind(this)中的this是btn对象。当某个btn对象被点击的时候,让disabled生效,三秒后执行定时器函数,bind的特性是函数不会立即执行,所以让定时器函数内部的this变成btn后三秒后再执行,dispaled失效解除禁用。
最后的总结
通过这个案例可以很好地知道bind是如何改变this的以及他的三个特性。特别是与call,aply不一样的一个点是不会立即执行这个函数。
所以bind方法适用于不立即执行函数且需改变this的情况下。