jQuery/JavaScript "this"指针混乱问题

26

当调用函数bar时,“this”的行为让我感到困惑。请看下面的代码。是否有办法使“this”在从单击处理程序调用 bar 时成为一个普通的 JavaScript 对象实例,而不是成为 HTML 元素?

// a class with a method

function foo() {

    this.bar();  // when called here, "this" is the foo instance

    var barf = this.bar;
    barf();   // when called here, "this" is the global object

    // when called from a click, "this" is the html element
    $("#thing").after($("<div>click me</div>").click(barf));
}

foo.prototype.bar = function() {
    alert(this);
}

请解释 "this" 是 foo 实例。 下面的 jsfiddle(http://jsfiddle.net/yY6fp/1/) 演示了 thisthis.bar() 中被评估为 window(全局)对象。 - Kevin Meredith
7个回答

37

欢迎来到JavaScript的世界!:D

您已经进入了JavaScript作用域和闭包的领域。

简短回答:

this.bar()

代码在foo的作用域下执行(因为this指向foo

var barf = this.bar;
barf();

该函数在全局作用域下执行。

this.bar基本上意味着:

使用this(foo)的作用域来执行this.bar指向的函数。当你将this.bar复制到barf并运行barf时,Javascript理解为运行barf指向的函数,并且由于没有this,它只在全局作用域中运行。

为了纠正这个问题,你可以更改

barf();

变成像这样:

barf.apply(this);

这告诉JavaScript在执行barf之前将this的作用域绑定到barf。

对于jQuery事件,您需要使用匿名函数或扩展原型中的bind函数以支持作用域。

更多信息:


2
我自己对术语并不完全确定,但我认为这个答案(以及链接到的资源)将“作用域”与“执行上下文”混淆了。this指向的对象是执行上下文,与作用域(闭包所涉及的内容)完全独立。作用域在函数创建时确定,并确定函数可以看到哪些变量;执行上下文在每次调用函数时确定,并确定this指的是什么。在此处将“作用域”替换为“执行上下文”,然后才会正确 - 我想! - Mark Amery

6

在 QuirksMode 网站上有一篇关于 JavaScript 中 this 关键字的很好的解释。QuirksMode


3

2

您可以在函数上使用Function.apply来设置this应该引用的内容:

$("#thing").after($("<div>click me</div>").click(function() {
    barf.apply(document); // now this refers to the document
});

1
除了你的代码缺少闭括号之外,函数 apply 立即执行函数 barf 而不是返回一个函数指针。 - Martin

2

1

这是因为始终是函数附加到的实例。对于EventHandler,它是触发事件的类。

您可以使用匿名函数来帮助自己,如下所示:

function foo() {
  var obj = this;
  $("#thing").after($("<div>click me</div>").click(function(){obj.bar();}));
}

foo.prototype.bar = function() {
  alert(this);
}

0
this.bar();  // when called here, "this" is the foo instance

当foo作为普通函数而不是构造函数使用时,此注释是错误的。

foo();//this stands for window

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