【问题标题】:JavaScript losing "this" object reference with private/public propertiesJavaScript 丢失带有私有/公共属性的“this”对象引用
【发布时间】:2010-07-23 21:15:02
【问题描述】:

运行以下页面时出现以下错误:

“this.testpublic 不是函数”


test = function() {
        var testprivate = function() {
                this.testpublic();
        }

        this.testpublic = function() {
                console.log('test');
        }

        testprivate();
}
new test();

显然,当testprivate 被调用时,“this”开始指向“window”而不是对象。

JavaScript 不应该在同一个对象中保留“this”上下文吗?

【问题讨论】:

    标签: javascript scope window this


    【解决方案1】:

    调用 testprivate 时需要操作上下文。您可以使用 function.call 覆盖函数的范围。试试这个:

    test = function() {
            var testprivate = function() {
                    this.testpublic();
            }
    
            this.testpublic = function() {
                    console.log('test');
            }
    
            testprivate.call(this);
    }
    new test();
    

    【讨论】:

      【解决方案2】:

      问题在于 this 实际上从一开始就没有引用 test 对象。它总是指最近的封闭对象——在这种情况下是window

      test = function() {
              var testprivate = function(say) {
                      console.log('test', say);
              }
      
              this.testpublic = function(say) {
                      testprivate('test', say);
              }
      
              testprivate();
      }
      x = new test();
      

      这是可行的,因为据我了解,this 是在 call 时间确定的——并且它被锁定在最近的“封闭”对象*中,除非 call()apply()被使用了。

      *这可能有一个much更好的词,但我不知道它是不是在我的脑海中。如果有人知道,请赐教:-)

      【讨论】:

        【解决方案3】:

        不,不应该。该函数仅定义范围。

        当您调用 foo.bar() 时,this(在 bar() 内部)是 foo。由于本例中没有显式的foo,所以默认为window

        this 在使用 new 关键字时的处理方式有所不同,但不适用于该调用)

        【讨论】:

          【解决方案4】:

          正如 Sean 所说:您实际上并没有创建对对象的新引用(创建 this 上下文),因为您只是在调用构造函数 - 而不是利用构造函数来创建新对象。如果您使用 new 关键字,它的效果非常好。

          由于调用时test()的作用域是window,所以在test()中调用的任何函数都会在test()中执行窗口 范围。

          通过使用 new 关键字,您将一个新对象分配到内存 - 并创建一个新范围。

          例如,在 firebug 中试试这个:

          var myFunction = function() {
              this.memberVariable = "foo";
              console.log(this);
          }
          myFunction();
          console.log(window.memberVariable);
          var myObject = new myFunction();
          console.log(myObject.memberVariable);
          

          你会看到这个结果:

          Window stats
          foo
          Object { memberVariable="foo"}
          foo
          

          Function 基础对象有一个方法,call(),正如 Craig 所述,它允许您明确指定函数应在哪个范围内运行:

          var myFunction = function() {
              this.memberVariable = "foo";
          }
          myFunction.call(myFunction);
          console.log(myFunction); // "Function()"
          console.log(myFunction.memberVariable); // "foo"
          

          然而,这不是首选的做事方式,因为您实际上并没有在这里创建一个新对象,并且 typeof myFunction 仍然会返回“function”而不是“object”——当你真的只是想创建一个对象。

          【讨论】:

            猜你喜欢
            • 2014-10-07
            • 2017-02-05
            • 1970-01-01
            • 1970-01-01
            • 2018-05-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-28
            相关资源
            最近更新 更多