在Javascript中,为什么;这";操作员不一致?

在Javascript中,为什么;这";操作员不一致?,javascript,Javascript,在JavaScript中,“this”操作符可以在不同的场景下引用不同的内容 通常在JavaScript“对象”中的方法中,它引用当前对象 但当用作回调时,它将成为对调用对象的引用 我发现这会导致代码中出现问题,因为如果使用JavaScript“对象”中的方法作为回调函数,则无法判断“this”是指当前的“对象”还是“this”指调用对象 有人能澄清如何绕过这个问题的用法和最佳实践吗 function TestObject() { TestObject.protot

在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');
            }
        }

我相信这可能是由于[closures](闭包)的思想是如何在Javascript中工作的

我自己刚刚开始处理闭包问题。请阅读维基百科的链接文章

这里有更多的信息


有没有人能够确认这一点?

一旦从其他上下文调用回调方法,我通常会使用我称之为回调上下文的东西:

var ctx = function CallbackContext()
{
_callbackSender
...
}

function DoCallback(_sender, delegate, callbackFunc)
{
 ctx = _callbackSender = _sender;
 delegate();
}

function TestObject()
{
   test = function()
  {
     DoCallback(otherFunc, callbackHandler);
  }

  callbackHandler = function()
{
 ctx._callbackSender;
 //or this = ctx._callbacjHandler;
}
}

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

myObject.myFunction();
然后
这个
内部的
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');
    }
}

对应于函数调用的上下文。对于未作为对象一部分调用的函数(无
运算符),这是全局上下文(
网页中的窗口
)。对于作为对象方法调用的函数(通过.operator),这是对象

但是,您可以随意设置。所有函数都有.call()和.apply()方法,可用于通过自定义上下文调用它们。因此,如果我像这样设置对象:

var Chile = { name: 'booga', stuff: function() { console.log(this.name); } };
…并调用Chile.stuff(),它将产生明显的结果:

booga
但如果我愿意,我可以拿着它真的去搞砸它:


这实际上非常有用…

您也可以使用Function.Apply(thisArg,argsArray)…其中thisArg确定函数中此参数的值…第二个参数是可选参数数组,您也可以将其传递给函数

如果不打算使用第二个参数,请不要向其传递任何内容。如果将null(或任何非数组的内容)传递给function.apply()的第二个参数,Internet Explorer将向您抛出TypeError

根据您给出的示例代码,它看起来像:

YAHOO.util.Connect.asyncRequest(method, uri, callBack.Apply(this));

在我喋喋不休地谈论这个变量的神奇之处之前,快速给出最佳实践的建议。如果你想要面向对象编程(OOP)在与更传统/经典的继承模式密切相关的Javascript中,选择一个框架,学习它的怪癖,不要试图变得聪明。如果你想变得聪明,请将Javascript作为一种函数语言学习,并避免考虑类之类的事情

这就引出了关于Javascript的最重要的一点,当它没有意义时,请您自己重复。Javascript没有类。如果某个东西看起来像类,这是一个聪明的把戏。Javascript有对象(无需使用嘲讽性引号)和函数。(这并不是100%准确,函数只是对象,但有时将它们视为独立的东西会有所帮助)

此变量附加到函数。无论何时调用函数,都会根据调用函数的方式为其指定特定值。这通常称为调用模式

javascript中有四种调用函数的方法。您可以将函数作为方法、函数、构造函数和应用程序调用

作为一种方法 方法是附加到对象的函数

var foo = {};
foo.someMethod = function(){
    alert(this);
}
当作为方法调用时,它将绑定到函数/方法所属的对象。在本例中,它将绑定到foo

作为一项功能 如果您有一个独立函数,此变量将绑定到“全局”对象,几乎总是浏览器上下文中的窗口对象

 var foo = function(){
    alert(this);
 }
 foo();

<强>这可能是绊倒你的“<强”,但不要感觉不好。很多人认为这是一个糟糕的设计决定。因为回调被调用为函数而不是方法,这就是为什么你看到什么是不一致的行为。

很多人通过这样做来回避这个问题

var foo = {};
foo.someMethod = function (){
    var that=this;
    function bar(){
        alert(that);
    }
}
您定义了一个指向此的变量。闭包(它自己的一个主题)将
保持在周围,所以如果您将bar作为回调调用,它仍然有一个引用

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

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

function Foo(){
    this.confusing = 'hell yeah';
}
var myObject = new Foo();
当作为构造函数调用时,将创建一个新对象,该对象将绑定到该对象。同样,如果您有内部函数,并且它们被用作回调,则您将作为函数调用它们,并且这将绑定到全局对象。使用该
var that=this;
trick/pattern

有些人认为constructor/new关键字是Java/传统OOP程序员用来创建类似类的东西的一块骨头

使用Apply方法。 最后,每个函数都有一个名为
apply
的方法(是的,函数是Javascript中的对象)。apply允许您确定该方法的值,还允许您传入一个参数数组。下面是一个无用的示例

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

如果您使用的是Prototype,那么您可以使用并绕过该问题。

如果您使用的是jav
function foo(a,b){
    alert(a);
    alert(b);
    alert(this);
}
var args = ['ah','be'];
foo.apply('omg',args);
var myObject = new TestObject();
myObject.firstMethod.bind(myObject);
callBack.bind(this);