JavaScript中的"this"用法让我感到困惑

27

在使用JavaScript时,最容易让人感到困惑的事情之一是使用this关键字。

var x = {  
  ele : 'test',
  init : function(){ 
    alert(this.ele);
  }
}

然而,在处理多个对象以及特别是事件上下文时,this的上下文会发生变化,难以跟踪和理解。

因此,如果有人有更好的输入/指导方针/想法/最佳实践,请分享。另外,我想了解是否使用 this 会带来任何(性能)优势或其他方面的影响?


8
不仅是你,这是语言中更令人困惑的方面之一。你应该会得到一些好的答案,我期待着阅读它们。 - Drew Wills
5个回答

28

这不是关于性能的问题,而是关于访问对象特定实例的属性的问题:

x.init()

如果没有在函数中使用this,将不会显示“test”。

实际上,以上代码与以下代码相同:

x.init.call(x);

在使用call时,第一个参数在函数执行时被赋值给this

现在考虑:

var fn = x.init;  //Note no () so the function itself is assigned to the variable fn
fn();

现在你在警报中没有得到任何内容。这是因为以上代码实际上是:

fn.call(window);
在浏览器中运行的 JavaScript 中,window 对象等同于全局对象。当直接调用函数时,this 默认为全局对象。
经典错误是这样写的:-
var x = {
   ele: 'test';
   init: function(elem) { 
      elem.onclick = function() { alert(this.ele); }
   }
}
x.init(document.getElementById('myButton'));

但是这种方法不起作用,因为附加到onclick事件的函数是由浏览器使用类似以下代码的方式调用的:

onclick.call(theDOMElement)

因此当函数运行时,this并不是你想象中的那样。

我通常解决这种情况的方法是:

var x = {
   ele: 'test';
   init: function(elem) {
      var self = this; 
      elem.onclick = function() { alert(self.ele); }
      elem = null;
   }
}
x.init(document.getElementById('myButton'));

注意elem = null是解决IE内存泄漏的方法。


我认为应该是 x.init() 而不是 e.init(),但编辑少于6个字符,所以我无法提交它。 - Moby Disk

6

这很令人困惑。它取决于你如何调用函数。Doug Crockford在他的书JavaScript语言精粹中写得非常好。其要点在这个出色的答案中,回答了一个形式不佳的问题。

不,这与性能无关。


3

对我来说,以下准则非常有帮助:每当你看到this时,请想象它是owner。拥有变量名称的对象将成为this。如果你无法理解谁拥有它,那么this将会是window。


2

使用

var me = this;

在技术领域之外

function(){

那么在函数()内部,您可以引用我。

2

一篇关于 this 关键字的好文介绍是这个(没有双关语的意思)。我相信这篇文章会为你解惑,因为它对我很有帮助。

本质规则是:函数内部的 this 关键字总是指向该函数的所有者。了解函数何时被引用和复制是理解其后果的关键。请参考前面提到的文章了解更多示例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接