【问题标题】:Javascript: How to get a reference to the parent object when "this" has been overwritten with "call"?Javascript:当“this”被“call”覆盖时,如何获取对父对象的引用?
【发布时间】:2011-06-02 17:27:27
【问题描述】:

好的,我现在讨厌 Javascript,希望有人可以帮助我。

我的代码设置如下:

function Obj1() {
    var me = this;

    this.something = "yay";

    this.getThis = function(){
        return me;
    }
}

Obj1.prototype.method = function() {
    return this.something;
};

function Obj2() {
    this.something = "nay";

}
Obj2.prototype.method = function() {
    return this.something;
}; 



var o1 = new Obj1();
var o2 = new Obj2();

document.write(o1.method()); // Returns yay
document.write(o1.method.call(o2));   // Returns nay, but I need "yay" here

(JSFiddle@http://jsfiddle.net/A9u9K/)

我的问题是,我需要在第二种情况下调用 Obj1.method,但我绝对无法获得对该对象的引用:(

我该如何解决这个问题?

编辑:抱歉,我的示例代码非常错误 :( 更新了它。我从之前的答案中获取了大部分代码,因为它更好并且仍然说明了我的问题。

【问题讨论】:

  • 代码正在做你要求它做的事情。您要求 javascript 引擎在 Obj1() 中调用 method() 方法,范围为 obj2。如果您只想在Obj1 中调用method(),那么您可以在obj1.method 处停止,就像您的情况1 一样。这就是javascript 引擎与对象作用域一起工作的方式,所以如果您在一个对象中调用一个方法,作用域为另一个对象那么被调用方法中的this关键字将指向作用域对象。
  • 是的,我的问题是,我有一些代码执行“o1.method.call(o2)”,但在那个方法中,我需要引用 o1 来做事。无论如何,我通过阅读 T.J. 的链接解决了我的问题。克劳德(非常感谢:D)

标签: javascript scope closures


【解决方案1】:

更新答案

document.write(o1.method.call(o2)); // Returns nay, but I need "yay" here

你说你现在已经把它整理好了,但是由于的答案实际上并没有在 SO 上显示,我想我不妨更新一下来显示它。 p>

如果它是method,您想要访问me,即使它被使用不同的this 值调用,您也必须将其定义为getThis,作为me 的闭包:

function Obj1() {
    var me = this;

    this.something = "yay";

    this.method = function() {
        return me.something;
    };

    this.getThis = function(){
        return me;
    };
}

function Obj2() {
    this.something = "nay";

}
Obj2.prototype.method = function() {
    return this.something;
};

...当然,如果您不需要“某物”作为对象的属性,只需在构造函数中将其设为 var(private variable,如 me):

function Obj1() {
    var me = this;
    var something = "yay";

    this.method = function() {
        return something;
    };

    this.getThis = function(){
        return me;
    };
}

function Obj2() {
    this.something = "nay";

}
Obj2.prototype.method = function() {
    return this.something;
};

原始答案(问题的修订版 1,没有me。)

但我认为,在创建闭包时(就像我在 4 中所做的那样)Javascript 应该保留“this”。

this完全由函数的调用方式设置,而不是在哪里定义;更多关于 herehere 的信息。但是您定义getThis 函数的方式,您可以使用它关闭构造函数调用的事实来解决这个问题(没有双关语)而不使用this

function Obj1() {
    var me = this;               // <== Use a variable to remember `this`

    this.something = "yay";

    this.method = function() {
        return this.something;
    };

    this.getThis = function(){
        return me;               // <== Return it
    };
}

Live example

更多关于闭包和使me 工作的管道here

这涉及到成本,并且通常在您定义函数的模式中构造函数中:Obj1Obj2 创建的每个单独的对象都有自己的 每个函数的副本。如果有很多这样的对象在运行,这可能会影响内存(但除非你有很多,否则你不必担心,你会得到像 me 和其他 private variables 这样的好处)。相反,如果您使用分配给原型的函数,则所有实例都将共享该函数的一个通用副本。

在您的示例代码中,真正需要为每个实例复制 getThis 函数(因为您依赖于闭包),因此您可以这样做以避免不必要的函数扩散:

function Obj1() {
    var me = this;

    this.something = "yay";

    this.getThis = function(){
        return me;
    };
}
Obj1.prototype.method = function() {
    return this.something;
};

function Obj2() {
    this.something = "nay";

}
Obj2.prototype.method = function() {
    return this.something;
};

【讨论】:

  • 是的,我也会以这种方式重写代码(在问题中):)
  • 我更新了示例代码以更好地说明我的问题(使用您的代码 sn-p)。在我的代码(以及您的代码)中,当“this”被覆盖时,我根本无法真正调用 getThis 方法,这使得它毫无意义。我搞砸了我之前的示例代码,对此感到抱歉。
  • @x3ro:那么问题现在解决了吗? (来自您对问题的评论。)如果是这样的话,很高兴这有帮助。
【解决方案2】:

【讨论】:

    【解决方案3】:

    问题在于 this 对象的引用在范围内发生了变化。 相反,如果在闭包中直接使用 this ,请使用等同于 this 的局部变量,即将 Obj1 更改为 L

    function Obj1() {
        this.something = "yay";
            var that = this;
    
        this.method = function() {
            return that.something;
        }
    
        this.getThis = function(){
            return that;
        }
    }
    

    【讨论】:

      【解决方案4】:

      解决这个问题的唯一方法是另一个占位符在Obj1 中保存this 的值,并在函数method()getThis() 中使用它。

      function Obj1() {
          var instance = this;
      
          this.something = "yay";
      
          this.method = function() {
              return instance.something;
          }
      
          this.getThis = function(){
              return instance;
          }
      }
      

      但我无法理解的是你为什么要这样做(obj1.getThis.call(obj2).method())? 这明确表示您想将方法 getThis() 的范围更改为其他内容,然后您正在尝试解决此用法造成的问题。

      你能说出你为什么想要这样的东西吗?

      【讨论】:

      • 其实,在我写例子的时候,我搞错了。我同意你的观点,这根本没有任何意义......我要编辑我的问题......
      猜你喜欢
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-22
      • 1970-01-01
      • 2020-04-18
      • 1970-01-01
      • 2021-03-28
      相关资源
      最近更新 更多