引子
习惯了别的语言的思维习惯而不专门了解 JavaScript 的语言特性的话,难免踩到一些坑。 上一篇文章 中简单总结了关于 提升, 严格模式, 作用域 和 闭包 的几个常见问题,当然这仅仅是了解 JavaScript 的一个开始,这次则依然从另一个大多人都见过但很容易搞错的概念开始了解 JavaScript 的不同之处 —— this。
首先看这段代码:
function plusOne() { this.count++; console.log("plusOne get called, this.count: " + this.count); } plusOne.count = 0; plusOne(); // 改成 plusOne.call(plusOne); console.log("plusOne.count = " + plusOne.count); console.log("window.count = " + window.count);我们知道 JavaScript 中所有的东西都是对象,那么很可能会把 this 自然的理解成当前对象“身上”的属性,对于上面的代码(注意,并非严格模式下),我们为 plusOne 创建了一个属性 count 并试图通过在 plusOne() 中使用 this.count++ 改变它的值。然而如果实际执行这段代码(注:假设是在浏览器 F12 的 Console 中),得到的结果会是这样:
plusOne get called, this.count: NaN plusOne.count = 0 window.count = NaN可以看出 plusOne() 中的 this.count 实际是 NaN,plusOne.count 却没有变化,并且 window.count 被创建了。而尝试按照上面代码中的注释那样把 plusOne() 改成 plusOne.call(plusOne) ,就会发现结果成了:
plusOne get called, this.count: 1 plusOne.count = 1 window.count = undefined那么为什么会这样呢?
this 是运行时到某个对象的绑定
首先分析上面的输出结果就可以知道,在我们使用 plusOne();时,this 并不是像想象的那样是一个指向 plusOne 的变量,而我们可以发现在浏览器中执行时 windows.count 被意外创建了,显然在这个情况,这里的 this.count 无意中在全局范围(即浏览器的 window)创建了 count ,而很明显 this 在此时 this 即绑定到了全局对象。至于值 NaN ,则是简单的
