使用“var that = this”了解Javascript范围

时间:2012-09-11 13:29:21

标签: javascript

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

  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内引用的任何属性都会以某种方式失去范围。

有人可以解释为什么我必须使用classificationSelectButton引用var that = this而不是仅仅调用`this.classificationSelectButton'吗?

6 个答案:

答案 0 :(得分:67)

最重要的是要理解一个函数对象没有固定的this - this的值会根据函数的调用方式而改变。我们说一个函数是用一些特定的this值调用的 - this值是在调用时确定的,而不是定义时间。

  • 如果函数被称为“原始”函数(例如,只做someFunc()),this将成为全局对象(浏览器中的window)(或{{ 1}}如果函数在严格模式下运行。)
  • 如果将其作为对象的方法调用,则undefined将成为调用对象。
  • 如果您使用callapply来调用某个功能,this被指定为thiscall的第一个参数。
  • 如果它被称为事件监听器(就像在这里一样),apply将是该事件的目标元素。
  • 如果将其作为this的构造函数调用,new将是一个新创建的对象,其原型设置为构造函数的this属性。
  • 如果函数是bind操作的结果,则该函数将始终永久地将prototype设置为生成它的this调用的第一个参数。 (这是“函数没有固定bind”规则的唯一例外 - this实际生成的函数具有不可变bind 。)

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

答案 1 :(得分:5)

因为this会根据其运行的上下文更改其值。

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

答案 2 :(得分:3)

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

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

词汇范围的规则非常直观。您可以明确指定变量。

然后是动态范围:this。这是一个神奇的事情,根据你如何调用一个函数来改变它的含义。它也被称为 context 。有几种方法可以赋予它意义。

考虑一个函数:

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

首先strict mode中的默认上下文为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中有very nice interactive slides上下文,您可以在其中学习和测试自己。

答案 3 :(得分:1)

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

有关this关键字的详情,请参阅https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/thishttp://www.quirksmode.org/js/this.htmlWhat is the scope of variables in JavaScript?

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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