【问题标题】:How does Javascript evaluate "this"?Javascript 如何评估“this”?
【发布时间】:2015-12-08 07:05:15
【问题描述】:

我正在尝试了解一些基本的 javascript。

我有以下sn-p。我们有 name 变量,在这两种情况下都通过 getName 方法引用。

第一个警报输出HocusPocus,而第二个警报输出GeorgeThomas。但我不明白在这种情况下this 是如何指代名称的

    var name = 'Gerorge Thomas';
    var obj = {
       name: 'Cinderella',
       value: {
          name: 'HocusPocus',
          getName: function() {
             return this.name;
          }
       }
    };
    
   alert( obj.value.getName() );
   var testing = obj.value.getName; 
   alert(testing());

【问题讨论】:

    标签: javascript variables object methods


    【解决方案1】:

    要理解这个问题,你必须了解 Javascript 如何在函数调用中设置this 的值。

    这里有所有方法的总结:When you pass 'this' as an argument

    对于您的特定情况,当您这样做时:

    var testing = obj.value.getName; 
    

    您现在有了对getName 函数的引用。您不再与obj.value 有任何联系。所以,test() 只是将getName 作为普通函数调用。在 Javascript 中进行普通函数调用时,this 的值要么是全局对象(在浏览器中为 window),要么在严格模式下是未定义的。

    在你的例子中,this 变成了window 对象,所以this.namewindow.name,它指向全局变量name,因此你得到结果'George Thomas'。

    事实上,如果你在strict模式下运行你的代码,它会导致一个错误,这实际上是严格模式的好处之一,它指出了这样的意外错误。


    另一方面,如果你执行一个obj.method()形式的函数,那么this被设置为obj。所以,当你这样做时:

    obj.value.getName()
    

    相当于:

    var o = obj.value;
    o.getName()
    

    这是调用函数的obj.method()形式,该函数会将this指针设置为对象,在本例中为obj.value


    可以通过多种方式解决此问题。这是使用.bind() 解决它的示例。

    var name = 'Gerorge Thomas';
    var obj = {
      name: 'Cinderella',
      value: {
        name: 'HocusPocus',
        getName: function() {
          return this.name;
        }
      }
    };
    
    document.write( obj.value.getName() + "<br>");
    var testing = obj.value.getName.bind(obj.value); 
    document.write(testing());

    【讨论】:

      【解决方案2】:

      好吧,它只需要一些思考,让我们分析一下:

      • 在第一个警报中,我们调用了getName() 方法 obj.value 对象所以它返回 obj.value.name 这是 "HocusPocus"

      alert( obj.value.getName() ); 我们称this.name 指的是obj.value 所以名字是HocusPocus

      • 但在第二个警报中,我们正在创建一个新函数testing() 使用getName() 方法的主体,因此它将附加到 全局 window 对象,如果我们调用它,我们将获得全局 name 的值是 'Gerorge Thomas'

      alert(testing()); 我们正在处理this.name,其中this 指的是全局范围,因此名称是'Cinderella'

      【讨论】:

        【解决方案3】:

        首先,您从obj 对象内部调用一个方法。第二次,您正在全局范围内制作函数的副本(不是真的,它只是一个参考)。所以你也可以为第二次通话写window.testing()。我认为这很清楚。

        【讨论】:

        • 根本没有创建函数的副本——仍然只有一个函数。将函数引用分配给第二个变量。但是,该任务与 OP 的问题无关。问题纯粹在于函数的调用方式。
        • 一个小技术细节在这里并不重要,但我相信你的话。
        • @DanMan - 这是您答案的全部前提,它是不正确的。 testing 是否在 not 的全局范围内实际上并不重要。即使它在函数范围内,也存在同样的问题。这与全局范围无关。
        • 这一切都在我的回答中得到了解释。当您调用obj.method() 时,method() 执行内部的this 指针设置为obj。因此,在您的第二个示例中,您已将一个名为 getName 的新方法附加到 obj2 并使用 obj2.getName() 调用它,因此,该方法中的 this 指针当然将指向 @987654333 @。您可能想阅读this other answer,了解如何在 Javascript 中设置 this
        • 所以这显然与范围有关。无论如何,请随时投票给我。
        猜你喜欢
        • 2011-08-14
        • 2013-05-06
        • 2014-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多