9

假设我在一个对象中有以下属性方法:

  onReady: function FlashUpload_onReady()
  {
     Alfresco.util.Ajax.jsonGet({
       url: Alfresco.constants.PROXY_URI + "org/app/classification",
       successCallback: {
         fn: function (o) {
           var classButtonMenu = [],
               menuLabel, that = this;

           var selectButtonClick = function (p_sType, p_aArgs, p_oItem) {
               var sText = p_oItem.cfg.getProperty("text");
               that.classificationSelectButton.set("label", sText);
           };

           for (var i in o.json.items) {
             classButtonMenu.push({
               text: o.json.items[i].classification,
               value: o.json.items[i].filename,
               onClick: {fn: selectButtonClick}
             });
           }

           this.classificationSelectButton = new YAHOO.widget.Button({
             id: this.id + "-appClassification",
             type: "menu",
             label: classButtonMenu[0].text,
             name: "appClassification",
             menu: classButtonMenu,
             container: this.id + "-appClassificationSection-div"
           });
         },
         scope: this
       },
       failureMessage: "Failed to retrieve classifications!"
     });

我花了一些猜测工作来弄清楚在selectButtonClick我需要引用that而不是this为了获得访问权限的函数中this.classificationSelectButton(否则它会出现undefined),但我不确定为什么我不能使用this. new YAHOO.widget.Button我最好的猜测是,一旦调用构造函数,整个对象中被引用的任何属性都会以某种方式失去作用域。

有人可以解释为什么我必须引用classificationSelectButtonvar that = this不是仅仅调用“this.classificationSelectButton”吗?

4

6 回答 6

74

要理解的最重要的事情是函数对象没有固定this——值的this变化取决于函数的调用方式。我们说一个函数是用某个特定的this调用的——该this值是在调用时确定的,而不是在定义时确定的。

  • 如果函数被称为“原始”函数(例如,只是 do someFunc()),this将是全局对象(window在浏览器中)(或者undefined如果函数在严格模式下运行)。
  • 如果它作为对象上的方法被调用,this则将是调用对象。
  • 如果使用callor调用函数applythis则将其指定为callor的第一个参数apply
  • 如果它被称为事件侦听器(就像这里一样),this它将是作为事件目标的元素。
  • 如果它作为构造函数调用new,this将是一个新创建的对象,其原型设置为prototype构造函数的属性。
  • 如果函数是bind操作的结果,则该函数将始终设置为产生它this的调用的第一个参数。bind(这是“函数没有固定this”规则的唯一例外——由bind实际生成的函数确实有一个不可变的this.)

Usingvar that = this;是一种this在函数定义时存储值的方法(而不是函数执行时间,什么时候this可以是任何东西,取决于函数的调用方式)。这里的解决方案是将 的外部值存储this在一个变量(传统上称为thator self)中,该变量包含在新定义的函数的范围内,因为新定义的函数可以访问在其外部范围内定义的变量。

于 2012-09-11T13:42:18.397 回答
5

因为this根据它运行的上下文改变它的值。

在您的selectButtonClick函数内部,this将引用该函数的上下文,而不是外部上下文。所以你需要this在外部上下文中给出一个不同的名称,它可以在selectButtonClick函数内部引用。

于 2012-09-11T13:32:55.080 回答
3

有词法范围:在函数中声明的变量和传递给函数的参数仅在函数内部(以及在其内部函数中)可见。

var x = 1; // `1` is now known as `x`
var that = this; // the current meaning of `this` is captured in `that`

词法作用域的规则非常直观。您明确分配变量。

然后是动态范围:this. 这是一个神奇的东西,它会根据你调用函数的方式改变它的含义。它也称为上下文。有几种方法可以为其赋予含义。

考虑一个函数:

function print() { console.log(this); }

首先,默认上下文是undefined严格模式,全局对象是普通模式:

print(); // Window

其次,您可以将其设为方法并使用对对象的引用、后跟和对函数的引用来调用它:

var obj = {};
obj.printMethod = print;
obj.printMethod(); // Object

请注意,如果您调用不带点的方法,则上下文将回退到默认值:

var printMethod = obj.printMethod;
printMethod(); // Window

最后,有一种分配上下文的方法是使用call/applybind

print.call(obj, 1, 2); // Object
print.apply(obj, [ 1, 2 ]); // Object

var boundPrint = print.bind(obj);
boundPrint(); // Object

为了更好地理解上下文,您可能需要尝试使用这些简单的示例。John Resig 有非常好的关于 JavaScript 上下文的交互式幻灯片,您可以在其中学习和测试自己。

于 2012-09-11T13:47:41.593 回答
1

将它存储在变量中可以让您在this可能引用其他内容的其他范围内访问它。

请参阅https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/thishttp://www.quirksmode.org/js/this.htmlJavaScript 中变量的范围是什么?有关this 关键字的更多信息。

于 2012-09-11T13:34:09.437 回答
1

当从 DOM 事件调用类的方法时,该this引用不起作用。例如,当对象的方法用作 onclick 的事件处理程序时,this指针指向事件发生的 DOM 节点。所以你必须this在对象中创建一个私有备份。

于 2012-09-11T13:36:11.100 回答
1

this是 javascript 中的关键字,而不是每个函数中定义的默认变量,因此,正如 Gareth 所说,this将引用调用函数的上下文,或者如果没有上下文,则引用全局对象。

于 2012-09-11T13:44:33.967 回答