JavaScript 的 this 关键字非常让人迷惑。实际上,对于一个函数,如果它是某个对象的方法,在该函数内部 this 就指向这个对象,否则 this 指向 window 对象。具体情形我们在下面一一列举出来。注意 this 的指向和函数的作用域没有必然联系,例如见下面的第 4 种情形。
(1)如果不在任何函数内部的话,this 指代的是 window 对象。例如:
var x = 1; alert(this.x) // 1
(2)如果在某个函数内部,this 指代该函数执行时所属的对象。例如:
var x = 1; function a() { alert(this.x); } a(); // 1 obj = {}; obj.x = 2; obj.b = a; obj.b(); // 2
(3)我们也可以用 call 或者 apply 函数直接指明 this 指代的对象。例如:
var x = 1; function a() { alert(this.x); } obj = {}; obj.x = 2; a.apply(obj); // 2
(4)如果内层函数包含在外层函数里面,内层函数的 this 指向 window 对象。例如:
var x = 1; obj = {} obj.x = 2; obj.a = function() { alert(this.x); function b() { alert(this.x); } b(); }; obj.a(); // 2 and 1
《JavaScript 语言精粹》中(第28页)称这个问题为 JavaScript 语法设计的一个错误。
(5)如果该函数被作为构造函数调用,this 指向所生成的新对象。例如:
var x = 1; A = function() { this.x = 2; var x = 3; }; obj = new A(); alert(obj.x); // 2 alert(x); // 1
(6)在 HTML 元素的属性中指明事件处理代码时,this 指向 window 对象。例如:
<html> <body> <script> var value = "window"; var test = function() { alert(this.value); // window }; </script> <input type="button" value="clickit" onclick="test()"/> </body> </html>
(7)在 JavaScript 代码中用 DOM 元素的事件属性指明事件处理函数时,this 指向该 DOM 元素。例如:
<html> <body> <input type="button" id="btn" value="clickit"/> <script> var value = "window"; var test = function() { alert(this.value); // clickit }; document.getElementById("btn").onclick = test; </script> </body> </html>
(8)在 IE 浏览器 中用 attachEvent 函数绑定事件处理函数时,this 指向 window 对象。例如:
<html> <body> <input type="button" id="btn" value="clickit"/> <script> var value = "window"; var test = function() { alert(this.value); // window }; document.getElementById("btn").attachEvent('onclick', test); </script> </body> </html>
(9)在非 IE 浏览器中用 addEventListener 函数绑定事件处理函数时,this 指向该 DOM 元素。例如:
<html> <body> <input type="button" id="btn" value="clickit"/> <script> var value = "window"; var test = function() { alert(this.value); // clickit }; document.getElementById("btn").addEventListener("click", test, false); </script> </body> </html>
参考资料:
[1] Javascript的this用法
[2] Private Members in JavaScript
[3] The this keyword
[4] Advanced event registration models
[5] element.onclick
[6] element.addEventListener
[7] 摆脱JavaScript中的绑定局面(译文)