代码之家  ›  专栏  ›  技术社区  ›  Jonathan Swinney

在javascript的父闭包中引用“this”

  •  9
  • Jonathan Swinney  · 技术社区  · 15 年前

    function Z( f )
    {
      f();
    }
    
    function A()
    {
      this.b = function()
      {
        Z( function () { this.c() } );
      }
    
      this.c = function()
      {
        alert('hello world!');
      }
    }
    
    var foo = new A();
    foo.b();
    

    可以通过以下方式实现:

    function Z( f )
    {
      f();
    }
    
    function A()
    {
      var self = this;
      this.b = function()
      {
        Z( function () { self.c() } );
      }
    
      this.c = function()
      {
        alert('hello world!');
      }
    }
    
    var foo = new A();
    foo.b();
    

    3 回复  |  直到 15 年前
        1
  •  6
  •   Nick Craver    15 年前

    保持对父级的引用(如您所拥有的)是一个好方法,但是对于您的特定示例,不需要匿名包装器,您可以直接传递函数,如下所示:

    var self = this;
    this.b = function()
    {
      Z(self.c);
    }
    

    You can test it out here ,如果没有这个包装,实际上就不需要 self 变量,你可以使用 this 直接,像这样:

    this.b = function()
    {
      Z(this.c);
    }
    

    You can test that version here .


    由于下面的注释中似乎有些混乱,所以上面的代码保持 ,如果要维护 /回调中的上下文,使用 .call() like this

    this.b = function()
    {
      Z.call(this, this.c);
    }
    

    为了 Z

    function Z( f )
    {
      f.call(this);
    }
    

    You can test it here .

        2
  •  1
  •   BrunoLM    15 年前

    您也可以使用

    this.b = function()
    {
        Z( (function () { this.c() }).apply(this) );
    }
    
        3
  •  1
  •   Lee    15 年前

    有一种模式通常被称为“委托”,它解决了这个问题。

    /** class Delegate **/
    var Delegate = function(thisRef, funcRef, argsArray) {
        this.thisRef=thisRef;
        this.funcRef=funcRef;
        this.argsArray=argsArray;
    }
    Delegate.prototype.invoke = function() {
        this.funcRef.apply(this.thisRef, this.argsArray);
    }
    /** static function Delegate.create - convenience function **/
    Delegate.create = function(thisRef, funcRef, argsArray) {
        var d = new Delegate(thisRef, funcRef, argsArray);
        return function() {  d.invoke(); }
    }
    

    this.b = function() {
      Z( Delegate.create(this, this.c) );
    }
    

    您还可以编写期望接收委托的函数:

    function Z( d ) {
        d.invoke();
    }
    

    然后,在 A b 变成:

    this.b = function() {
        var d = new Delegate(this, this.c);
    
        Z( d );
        SomeOtherFunc( d );
    }
    

    这个 Delegate 只是提供了一种简单、一致的方法来封装 this 参考号 self ),在可以像处理任何其他对象实例一样处理的对象实例中。它更具可读性,并且避免了使用诸如 . 更高级的委托实现可以有自己的方法和其他相关状态。也可以通过这样的方式来构建委托,从而帮助最小化一些与作用域相关的内存管理问题(尽管我在这里展示的代码绝对不是这样的示例)。