在Javascript中,为什么"this"运算符不一致?

26 javascript

在JavaScript中,"this"运算符可以在不同的场景下引用不同的东西.

通常在JavaScript"对象"内的方法中,它引用当前对象.

但是当用作回调时,它将成为对调用对象的引用.

我发现这会导致代码出现问题,因为如果你在JavaScript"对象"中使用一个方法作为回调函数,你无法判断"this"是指当前的"对象"还是"this"是指调用对象.

有人可以澄清如何解决这个问题的用法和最佳实践吗?

   function TestObject() {
            TestObject.prototype.firstMethod = function(){
                      this.callback();
                      YAHOO.util.Connect.asyncRequest(method, uri, callBack);

            }

            TestObject.prototype.callBack = function(o){
              // do something with "this"
              //when method is called directly, "this" resolves to the current object
              //when invoked by the asyncRequest callback, "this" is not the current object
              //what design patterns can make this consistent?
              this.secondMethod();
            }
            TestObject.prototype.secondMethod = function() {
             alert('test');
            }
        }
Run Code Online (Sandbox Code Playgroud)

Ala*_*orm 82

关于最佳实践的快速建议,然后我就这个变量的魔法喋喋不休.如果你想在Javascript中使用面向对象编程(OOP)来密切反映更传统/经典的继承模式,那么选择一个框架,学习它的怪癖,不要试图变得聪明.如果你想变得聪明,学习javascript作为一种功能语言,并避免考虑像类这样的事情.

这引出了关于Javascript的最重要的事情之一,并在没有意义时重复自己.Javascript没有类.如果看起来像一个类,这是一个聪明的把戏.Javascript有对象(不需要嘲弄引用)和函数.(这不是100%准确,函数只是对象,但将它们视为单独的东西有时会有所帮助)

这个变量被附连到功能.当你调用一个函数,这个被赋予了一定的价值,这取决于你如何调用该函数.这通常称为调用模式.

有四种方法可以在javascript中调用函数.您可以将函数作为方法,函数,构造函数apply来调用.

作为一种方法

方法是附加到对象的函数

var foo = {};
foo.someMethod = function(){
    alert(this);
}
Run Code Online (Sandbox Code Playgroud)

当作为一种方法被调用,将被绑定到对象的功能/方法是的一部分.在这个例子中,这将绑定到foo.

作为一个功能

如果你有一个独立的函数,这个变量将被绑定到"全局"对象,几乎总是在浏览器的上下文中的窗口对象.

 var foo = function(){
    alert(this);
 }
 foo();
Run Code Online (Sandbox Code Playgroud)

这可能是绊倒你,但不要感觉不好.很多人认为这是一个糟糕的设计决定.由于回调是作为函数而不是作为方法调用的,因此您可以看到看似不一致的行为.

很多人通过这样做来解决这个问题

var foo = {};
foo.someMethod = function (){
    var that=this;
    function bar(){
        alert(that);
    }
}
Run Code Online (Sandbox Code Playgroud)

你定义一个变量指向这个.Closure(一个它自己的主题)保持that不变,所以如果你把bar称为回调,它仍然有一个引用.

作为构造函数

您还可以将函数作为构造函数调用.根据您正在使用的命名约定(TestObject),这也可能是您正在做的事情,也是您绊倒的原因.

您使用new关键字将函数作为构造函数调用.

function Foo(){
    this.confusing = 'hell yeah';
}
var myObject = new Foo();
Run Code Online (Sandbox Code Playgroud)

当作为一个构造函数调用时,一个新的对象将被创建,并且将被绑定到该对象.同样,如果你有内部函数,他们正在使用回调,你会被调用它们的功能,并且将被绑定到全局对象.使用那个var that = this;技巧/模式.

有些人认为构造函数/ new关键字是Java /传统OOP程序员抛出的骨骼,作为创建类似于类的东西的方法.

使用Apply方法.

最后,每个函数都有一个方法(是的,函数是Javascript中的对象)apply.应用可以让你决定的价值来决定将是,也可以让你在参数数组传递.这是一个无用的例子.

function foo(a,b){
    alert(a);
    alert(b);
    alert(this);
}
var args = ['ah','be'];
foo.apply('omg',args);
Run Code Online (Sandbox Code Playgroud)

  • 可能值得补充:还有call方法,其功能类似于apply,除了参数不作为数组传递. (6认同)

Ric*_*cky 12

在JavaScript中,this始终引用调用正在执行的函数的对象.因此,如果函数被用作事件处理程序,this则将引用触发事件的节点.但如果你有一个对象并在其上调用一个函数,如:

myObject.myFunction();
Run Code Online (Sandbox Code Playgroud)

然后this里面myFunction会参考myObject.是否有意义?

要解决它,你需要使用闭包.您可以按如下方式更改代码:

function TestObject() {
    TestObject.prototype.firstMethod = function(){
        this.callback();
        YAHOO.util.Connect.asyncRequest(method, uri, callBack);
    }            

    var that = this;
    TestObject.prototype.callBack = function(o){
        that.secondMethod();
    }

    TestObject.prototype.secondMethod = function() {
         alert('test');
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 链接到关于javascript中关闭的非常好的演示文稿:http://tinyurl.com/5mrpjv (2认同)