javascript中的bind

  写这篇博客完全是因为前面写的贪吃蛇游戏,所以说写些有兴趣的代码还是可以发现和学习到很多自己平时看书注意不到的东西的,建议大家要多学多看多练。嗯,下面就开始今天的笔记吧。

  简单来说问题是这样的:我写了一个类,里面的一个方法要利用window.setInterval()来周期运行这个类的另一个方法,理所当然我会把第一个参数写成this.xxx,结果当然是不停的报错,错误信息是this.xxx is undefined。我检查了好几遍发现我确实定义了该函数啊,为什么会说没定义呢?
  我纠结了一个午饭的时间,下午休息过后决定还是看看有没有前人的经验可以借鉴,然后就发现了这篇点我点我点我,里面说到了根本的问题:经过setInterval的调用后,this就变成浏览器,也就是全局域了,在全局作用域里当然是没有该函数的,所以肯定会报错的。里面说的一个方法可以解决我们的问题,那就是定义一个成员变量self,并把this赋值给它,然后再在setInterval中利用self来代替this继而避免this的意义的偷偷转变造成的错误。
  上面的办法是可行的,我尝试并成功了。但是,但是,在这边文章下面的留言里我看到了一种更好的办法,那就是利用this.xxx.bind(this)来解决。(啊摔,其实,我是没看到这个留言才用了上面的方法。上面的方法总感觉有种小题大作的感觉,因为你要把内部所有的this都换成self。)
  好的,我们要心平气和的来理解下bind。首先,我们看下MSDN上对其的解释:对于给定函数,创建具有与原始函数相同的主体的绑定函数。在绑定函数中,this对象将解析为传入的对象。绑定函数具有指定的初始参数

1
function.bind(thisArg[,arg1[,arg2[,argN]]])

  上面的调用方法中,thisArg是this关键字可在新函数中引用的对象,该值必选。后面的就是一系列可选的要传递到新函数的参数的列表。官方对其的使用场景也有说明:它用于为在其他上下文中执行的函数保留执行上下文。这个不正是我们需要的么?我们在执行setInterval的时候正是由于上下文的丧失才造成了this的指代错误。好的,我们再来看一下官方的例子理解一下用法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var data;
var dataReadyEvent = document.createEvent("Event");
dataReadyEvent.initEvent("dataReady", true, false);
function DataObject() {
this.name = "Data Object";
this.data = function () {
return data;
}
this.onDataCompleted = dataReadyHandler;
document.addEventListener('dataReady', this.onDataCompleted.bind(this));
// To see the result of not using bind, comment out the preceding line,
// and uncomment the following line of code.
// document.addEventListener('dataReady', this.onDataCompleted);
}
function dataReadyHandler() {
if (console && console.log) {
console.log("Data object property value: " + this.name);
console.log("Data object property value: " + this.data());
}
}
setTimeout(function () {
data = [0, 1, 2, 3];
document.dispatchEvent(dataReadyEvent);
}, 5000);
}
var dataObj = new DataObject();
// Output:
// Data Object
// 0,1,2,3

  该例子还是很好的说明了问题的,如果按照前面的理论,类似documentwindow的函数调用是会改变上下文的,那么this.namethis.data()定会是全局作用域中的,此时就会报错了。但我们看到的是,输出的都是类DataObject中的参数或者方法的结果,说明bind还是起了作用的,也就是this.onDataCompleted.bind(this)返回的函数中将会把this解析为DataObject

版权:本文采用以下协议进行授权,自由转载 - 非商用 - 非衍生 - 保持署名 | Creative Commons BY-NC-ND 3.0,转载请注明作者及出处。