【问题标题】:Why is `goog.base(this)` necessary in addition to `goog.inherits()`?为什么除了 `goog.inherits()` 之外还需要`goog.base(this)`?
【发布时间】:2012-06-20 15:12:13
【问题描述】:

在这个涉及构造函数的 Google Closure javascript 代码的 sn-p 中,为什么需要 goog.base(this);Foo 不是已经从带有goog.inherits(foo, goog.Disposable); 的 Disposable 继承了吗?

goog.provide('Foo');

/**
 * @constructor
 * @extends {goog.Disposable}
 */
Foo = function() {
  goog.base(this);
}     
goog.inherits(foo, goog.Disposable);

foo.prototype.doSomething = function(){
  ...
}

foo.prototype.disposeInternal = function(){
  ...
}

【问题讨论】:

    标签: javascript inheritance prototypal-inheritance google-closure-library


    【解决方案1】:

    goog.inherits(childConstructor, parentConstructor)

    goog.inherits() 从子构造函数建立原型链 到父构造函数。

    /**
     * Inherit the prototype methods from one constructor into another.
     * @param {Function} childCtor Child class.
     * @param {Function} parentCtor Parent class.
     */
    goog.inherits = function(childCtor, parentCtor) {
      /** @constructor */
      function tempCtor() {};
      tempCtor.prototype = parentCtor.prototype;
      childCtor.superClass_ = parentCtor.prototype;
      childCtor.prototype = new tempCtor();
      /** @override */
      childCtor.prototype.constructor = childCtor;
    };
    


    除了原型属性,构造函数可能有“自己的”属性 (即添加到this 的特定于实例的属性)。由于goog.inherits() 不调用父构造函数,自己的属性不复制到 子构造函数和父中的任何初始化代码都没有得到 执行。由于这些原因,标准模式是chain constructors,如下例所示。

    /**
     * @param {string} name The parent's name.
     * @constructor
     */
    var Parent = function(name) {
      /**
       * @type {string}
       * @private
       */
      this.name_ = name;
    }
    
    /**
     * @param {string} name The child's name.
     * @constructor
     * @extends {Parent}
     */
    var Child = function(name) {
      Parent.call(this, name);
    }
    goog.inherits(Child, Parent);
    


    goog.base(self, opt_methodName, var_args)

    goog.base() 是一个辅助函数,用于调用父方法,这样你就可以 不需要显式使用call()apply()

    如果 [goog.base()] 从构造函数中调用,则 this 调用 参数为 1-N 的超类构造函数。

    如果这是从原型方法调用的,那么您必须传递 该方法作为此函数的第二个参数。如果你不, 你会得到一个运行时错误。这将调用超类的方法 参数 2-N。

    此功能仅在您使用goog.inherits 表示继承时有效 类之间的关系。

    在闭包代码中,通常使用goog.base() 链接构造函数而不是 而不是显式调用父构造函数。

    /**
     * @param {string} name The child's name.
     * @constructor
     * @extends {Parent}
     */
    var Child = function(name) {
      goog.base(this, name);
    }
    goog.inherits(Child, Parent);
    


    进一步阅读

    【讨论】:

    • 作为一个从Java 世界过来的人,说baseinherits 就像super()extends 一样有意义吗?
    【解决方案2】:

    在 JavaScript 中,this 完全由函数的调用方式设置,而不是在哪里定义(就像在 Java、C# 和 C++ 中一样)。因此,要使this 内调用goog.Disposable 成为您调用它的this,您必须使用.call.apply。否则,如果您刚刚调用了goog.Disposable(),则在调用this 中将是goog

    基本上,有两种方法可以为您正在调用的函数设置this

    1. 使用 obj.func()obj["func"]() 表示法 - 例如,将调用作为您从对象中检索属性的同一整体表达式的一部分。这告诉引擎在调用中,您希望this 引用obj

    2. 使用callapply 通过提供对象作为this 作为第一个参数来更明确地说明它。 callapply 之间的唯一区别是您如何提供其他参数:使用 call,您将它们作为离散参数提供,例如foo.call(obj, 1, 2, 3) 调用 foo 并将 this 设置为 obj 和参数 123。使用apply,您可以将参数作为类似数组的第二个参数提供:foo.apply(obj, [1, 2, 3]);(注意[];例如var a = [1, 2, 3]; foo.call(obj, a);

    更多探索:

    【讨论】:

    • 你能给出一个规范的答案,这样我们就可以把它当作副本使用,我看到你每天做这个答案 100 次:D
    • @Esailija:是的,它惊人出现了多少不同的上下文。:-) 有时它是完全重复的,其他时候(比如这个)它是 有效地重复,但你可以看到为什么有人不会找到更早的答案......
    【解决方案3】:

    你可以看到

    Foo = function() {
      goog.base(this); //call parent constructor
    }     
    goog.inherits(foo, goog.Disposable);
    

    作为:

    public class Foo extends Disposable(){
      public Foo(){
        super(); // call parent constructor
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 2018-07-08
      • 1970-01-01
      • 1970-01-01
      • 2012-03-03
      • 2016-04-20
      • 2018-01-14
      相关资源
      最近更新 更多