使用"var that = this"了解Javascript范围

Sco*_*ott 9 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!"
     });
Run Code Online (Sandbox Code Playgroud)

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

可能有人请解释为什么它是我必须引用classificationSelectButtonvar that = this而不只是调用`this.classificationSelectButton"?

aps*_*ers 70

最重要的是要理解一个函数对象没有固定this - this更改的值取决于函数的调用方式.我们说使用某个特定this值调用函数- 该this值是在调用时确定的,而不是在定义时确定的.

  • 如果函数被称为"原始"函数(例如,只做someFunc()),this则将是全局对象(window在浏览器中)(或者undefined如果函数在严格模式下运行).
  • 如果它被调用作为对象的方法,this则将是调用对象.
  • 如果你调用一个函数callapply,this被指定为第一个参数callapply.
  • 如果它被称为事件监听器(就像它在这里),this将是作为事件目标的元素.
  • 如果它被作为构造函数调用new,this则将是一个新创建的对象,其原型设置为prototype构造函数的属性.
  • 如果函数是bind操作的结果,则函数将始终并永远this设置为bind生成它的调用的第一个参数.(这是"函数没有固定this"规则的唯一例外- bind实际生成的函数确实具有不可变的this.)

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

  • 很有用!我写了一篇[Gist](https://gist.github.com/cyrus-and/8169187),总结了所有这些案例. (6认同)

Gar*_*eth 5

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

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