【问题标题】:What is the value of var me = this;var me = this 的值是多少?
【发布时间】:2011-09-15 19:53:58
【问题描述】:

我在 ExtJS 源代码中发现了这种模式。

method: function() {
  var me = this;
  ...
  me.someOtherMethod();
}

他们为什么不直接使用thisalways 经常定义me(除了不必输入 2 个字符)有什么好处吗?我可以理解他们是否试图通过闭包来维护上下文,但它是在根本没有闭包的地方完成的。

Ext.panel.Panel 的一个例子:

disable: function(silent) {
    var me = this;

    if (me.rendered) {
        me.el.addCls(me.disabledCls);
        me.el.dom.disabled = true;
        me.onDisable();
    }

    me.disabled = true;

    if (silent !== true) {
        me.fireEvent('disable', me);
    }

    return me;
},

【问题讨论】:

  • 我曾经使用过这种做法的唯一案例是使用新的上下文。你能提供一个特定的代码 sn-p 没有以这种方式使用吗?
  • 我希望人们继续为此投票。我选择了丹尼尔的答案,因为他首先想到了这个答案,并且符合我的问题的精神。
  • 也许有人真的不喜欢隐含的this 的想法?

标签: javascript extjs


【解决方案1】:

如果您的库在没有嵌入闭包/回调的地方执行此操作,而这些闭包/回调可能具有自己的 this 值,那么这只是他们决定的“实践”或“风格”或“约定”遵循他们的方法。没有编程理由总是这样做。

在您现在添加到问题中的特定编码示例中,除了常见的编码风格之外,我没有其他理由知道。此代码将生成相同的结果,但代码稍小:

disable: function(silent) {

    if (this.rendered) {
        this.el.addCls(this.disabledCls);
        this.el.dom.disabled = true;
        this.onDisable();
    }

    this.disabled = true;

    if (silent !== true) {
        this.fireEvent('disable', this);
    }

    return this;
},

当涉及回调或闭包时,通常会这样做,因为在方法内部使用了回调,他们仍然希望引用 this,但这些回调将具有自己的 this 值,因此分配:

var me = this;

或者在我见过的其他代码中更常见:

var self = this;

即使在具有不同 this 值的回调中也是一种保留对该对象的访问权限的方法。

这是一个通用示例:

document.getElementById("myButton").onclick = function () {
    var self = this;       // save reference to button object use later
    setTimeout(function() {
        // "this" is not set to the button inside this callback function (it's set to window)
        // but, we can access "self" here 
        self.style.display = "none";    // make button disappear 2 seconds after it was clicked
    }, 2000);
};

【讨论】:

  • 这也是我的想法,但 OP 自己也观察到,在回调中访问 this 是一种常见的做法。根据我的阅读,他特别问为什么在不涉及新上下文时也使用它。
  • 好的,我在我的答案中添加了一条评论,与没有回调/关闭时这样做有关。其中之一的特定代码示例会针对该特定案例生成更有意义的答案。
  • 好的,我现在评论一下添加到问题中的具体代码示例。
  • 没有编程的原因——它是为了缩小文件大小。 this 不能缩短,而me 可以。
  • @jfriend00,我不发表意见。我在说明确切地为什么要在 Ext 中完成。
【解决方案2】:

一个原因是因为通过缩小,me 可以变得比this 短得多。

【讨论】:

  • 当你缩小代码时,我可以变成'x'或'y'或比'this'更短的东西。缩小器不会修改“this”关键字。
  • 因此,如果他们要使用this 超过~3 次,就会有一些小的优势。可能在这里做点什么。
  • 我想这正是它的原因。我能想到的唯一另一件事是提供一个比this 提供的更具描述性的名称,尽管问题代码中的me 并没有真正提供这种好处。
  • 这听起来确实是一种可能的好处。使用 12 个字符来声明最小化版本 var a=this;\n 并使用 a 而不是 this 节省 3 个字符,如果对 this 的引用超过四个,您将节省字节。如果只有一两个对this 的引用,您将丢失几个字节。我确实想知道这是否是真正的动机,或者它是否真的只是一种保持所有方法一致的通用方法实现风格,即使是那些带有嵌入式闭包的方法。
  • 为什么 Javascript minificators 不做这个优化?这个原因对我来说似乎很可疑,这可能只是文件大小的 1-2%,不值得手动混淆你的原始代码。
【解决方案3】:

除了样式原因和缩小原因之外,我决定查看性能,看看thisself 是否更快。我创建了这个jsperf test

据我所知,在我尝试过的任何现代浏览器甚至 IE6 中,使用 this 与使用局部变量(如 selfme)在性能上基本上没有差异。使用self 时,Chrome 的速度会稍微快一些,而其他的则太接近而无法调用。我认为我们可以排除任何性能原因。这是我看到的结果的屏幕截图:

【讨论】:

    【解决方案4】:

    问题很可能与闭包函数有关,例如在注册回调时作为参数。在这种情况下,“this”可以有一个完全不同的值,所以他们需要使用“me”来代替。

    【讨论】:

      【解决方案5】:

      有时这样做是为了在闭包中保持范围,但主要是(如发布的示例中)允许缩小,因为 me 可以缩小到一个字符,而 this 不能更改。在给定函数中使用 this 大约 3 或 4 次后,这变得很重要(少于此值,您实际上可能会从额外的声明代码中得到一些额外的字节)。就这么简单——它与编程风格或奇思妙想无关。

      【讨论】:

        【解决方案6】:

        基于您刚刚添加的Ext.panel.Panel 示例,除非我对 Javascript 变量的理解非常错误,否则此处不进行赋值对代码的作用绝对没有影响。

        剩下的唯一可能就是风格。

        虽然我将其归为过度工程,但如果您想在这种情况下添加一个需要访问 this 的回调,则它很有用,您无需返回更改所有 @ 987654323@'s 到 me's。毕竟,输入:s/ 很难。

        【讨论】:

          【解决方案7】:

          实际上,虽然这可能不是动机,但为了风格而这样做是有道理的。许多样式约定是为了让忘记某些东西变得更加困难,例如总是将 { } 放在 else 块周围,即使它是单个语句。重新分配“this”会产生类似的影响,因为初级 JavaScript 程序员会在更高的时间里让闭包“正常工作”。

          【讨论】:

            【解决方案8】:

            除了维护用于闭包的上下文之外,我不知道使用该模式有任何编程差异。也许这只是 ExtJS 使用的一种约定。

            此外,正如 Daniel 所说,在缩小过程中可能会进一步缩短代码。 ExtJS、jQuery 等库非常关心文件大小,使用这种技术可能会节省足够的文件大小

            例如1000 'this',假设 1 char = 1 byte,是 4kb。使用上述技术可能会减少 2 或 3 kb。

            更新:继续做了一个小实验..

            var test = {
              a : function() {
                 this.x='';
                 this.x='';
                 this.x='';
                  this.x='';
                 this.x='';
                 this.x='';
                 this.x='';
                 this.x='';
                 this.x='';
                  this.x='';
                 this.x='';
                 this.x='';
              },
              b : function() {
                  this.x='';
                 this.x='';
                 this.x='';
                  this.x='';
                 this.x='';
                 this.x='';
                 this.x='';
                 this.x='';
                 this.x='';
                  this.x='';
                 this.x='';
                 this.x='';
              },
              c : function() {
                  this.x='';
                 this.x='';
                 this.x='';
                  this.x='';
                 this.x='';
                 this.x='';
                 this.x='';
                 this.x='';
                 this.x='';
                  this.x='';
                 this.x='';
                 this.x='';
              }
            }
            

            缩小成

            var test={a:function(){this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x=""},b:function(){this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x=""},c:function(){this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x="";this.x=""}}
            

            同时

            var test = {
              a : function() {
                 var me=this;
                 me.x='';
                 me.x='';
                 me.x='';
                  me.x='';
                 me.x='';
                 me.x='';
                 me.x='';
                 me.x='';
                 me.x='';
                  me.x='';
                 me.x='';
                 me.x='';
              },
              b : function() {
                  var me=this;
                 me.x='';
                 me.x='';
                 me.x='';
                  me.x='';
                 me.x='';
                 me.x='';
                 me.x='';
                 me.x='';
                 me.x='';
                  me.x='';
                 me.x='';
                 me.x='';
              },
              c : function() {
                  var me=this;
                 me.x='';
                 me.x='';
                 me.x='';
                  me.x='';
                 me.x='';
                 me.x='';
                 me.x='';
                 me.x='';
                 me.x='';
                  me.x='';
                 me.x='';
                 me.x='';
              }
            }
            

            缩小成

            var test={a:function(){var a=this;a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x=""},b:function(){var a=this;a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x=""},c:function(){var a=this;a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x="";a.x=""}}
            

            这意味着大约 10% 或多或少的字符(当然这取决于在代码的块范围内重复使用了多少“this”)。

            【讨论】:

            • 百分比变化更多地取决于函数中有多少其他代码。您的示例几乎没有其他代码,因此百分比变化将被放大。我们正在讨论为每个函数节省少量字节,当您克服声明 a 的额外开销后,当 this 替换为 a 时,每次使用“this”最多节省 3 个字节。
            • 如我的回答所示,节省实际上取决于您在代码的每个范围内使用“this”关键字的频率。我的意思是你可以用“我”替换“这个”多少次。 “this”关键字本身的出现次数并不能决定您可以替换它的次数(例如,每个函数中都有 1 个“this”)。
            【解决方案9】:

            专门针对 ExtJS 框架。

            ExtJS 有自己的机制来处理有问题的 Javascript 作用域,缩小是唯一使用var me = this 的原因。

            this Sencha Forum thread 中有更多关于该主题的详细信息。

            【讨论】:

              【解决方案10】:

              在使用 ExtJs 时,我没有发现这个约定很有用。我不经常使用闭包。在 AngularJs 等其他框架中工作时,这种约定为我节省了很多痛苦和痛苦。弄错范围是一个耗时的错误。一旦我开始使用这个约定,我就再也没有弄错范围了。

              【讨论】:

                猜你喜欢
                • 2016-09-21
                • 2012-05-13
                • 2011-11-06
                • 2011-07-16
                • 1970-01-01
                • 2012-12-07
                • 1970-01-01
                • 2022-12-02
                • 1970-01-01
                相关资源
                最近更新 更多