【问题标题】:Prototype chain in Javascript not updatedJavascript 中的原型链未更新
【发布时间】:2014-02-09 10:22:44
【问题描述】:

我正在尝试理解 Javascript 中的 原型继承,但未能适用于以下情况。任何帮助将不胜感激。

我正在定义一个构造函数如下:

var base = function() {
    var priv = "private"; // Private
    var publ = "public";  // Public through a getter/setter (below)

    // The object to return
    var f = {};

    f.publ = function (new_val) {
        if (!arguments.length) {
          return publ;
        }
        publ = new_val;
        return f;
    };

    return f;
};

使用这个构造函数,我可以通过调用base(); 创建对象。这些对象有一个公共方法(publ)。

现在,按照相同的结构,我想要一个新的构造函数,它创建的对象继承自上面定义的“基本构造函数”创建的对象:

var myclass = function () {

  // Other parameters defined here

  var f = function () {
      // publ is inherited
      console.log(f.publ());
  };

  // Trying to set the prototype of f to the object created by "base()"
  f.prototype = base();

  // Other methods defined here

  return f;
};

对于f.prototype = base();,我想让f继承base()返回的对象中定义的所有方法,但是尝试调用f.publ会报错,因为f没有方法publ

欢迎任何帮助了解正在发生的事情

M;

【问题讨论】:

  • javascript 中的原型继承需要new 运算符或Object.create。您在这里都没有使用。
  • 这看起来不像构造函数。您可以将构造函数与new 一起使用。它看起来更像是一个模块模式。
  • 如几个 cmets 中所述,使用 Object.create 设置继承的原型部分并在 Child 中执行 Parent.call(this,args)(这将负责从 Parent 继承实例成员)。更多信息在这里stackoverflow.com/a/16063711/1641941

标签: javascript prototypal-inheritance


【解决方案1】:

最常见的原型继承方式如下:

function Base() {
    var priv = "private";
    this.publ = "public";
}

您现在可以使用new Base 创建Base 的实例。接下来我们创建MyClass

MyClass.prototype = new Base;

function MyClass() {
    alert(this.publ);
}

最后,您可以使用new MyClass 创建MyClass 的实例,如下所示:

var a = new MyClass; // alerts "public"

亲自观看演示:http://jsfiddle.net/b3QyE/


JavaScript 中的原型继承可能会有些混乱,因为它是 constructor-centric instead of prototype-centric,这就是为什么我更喜欢使用以下实用函数来创建“类”:

function defclass(base, body) {
    var uber = base.prototype;
    var prototype = Object.create(uber);
    var constructor = (body.call(prototype, uber), prototype.constructor);
    constructor.prototype = prototype;
    return constructor;
}

使用defclass,您现在可以按如下方式重构您的代码:

var Base = defclass(Object, function () {
    this.constructor = function () {
        var priv = "private";
        this.publ = "public";
    };
});

var MyClass = defclass(Base, function (uber) {
    this.constructor = function () {
        uber.constructor.call(this);
        alert(this.publ);
    };
});

它更具可读性和可理解性。一切都被封装在一个单一的函数范围内,没有什么是悬而未决的。此外,您无需了解原型继承即可使用它。查看更新后的演示:http://jsfiddle.net/b3QyE/2/

如果您注意到我们正在从 MyClass 构造函数调用 Base 类构造函数。这允许您使用Base 类构造函数初始化实例。你可以通过uber调用Base类的任何方法。


要了解有关原型继承的更多信息,请查看以下答案:

  1. JavaScript inheritance and the constructor property
  2. How to achieve pseudo-classical inheritance right on the class declaration?
  3. Benefits of prototypal inheritance over classical?

【讨论】:

  • 注意:建立继承的更好方法是使用Object.create(Parent.prototype) 而不是new Parentstackoverflow.com/a/17393153/218196 edit: 这就是你在defclass 函数中所做的事情:D
  • 你在引用 Crockford 的话,这个人迄今为止还没有能够正确使用他自己所谓的“伪经典继承”的文章或演示文稿,也许 JavaScript 新手会受益更多关于如何使用构造函数和原型的正确文档,以便他们自己决定如何使用或不使用它。
  • @HMR 也许 JavaScript 新手会从学习 Haskell 中受益更多。说真的,学习 Haskell 会让你成为一个更好的 JavaScript 程序员。
猜你喜欢
  • 2012-07-02
  • 2016-04-10
  • 1970-01-01
  • 1970-01-01
  • 2015-05-02
  • 1970-01-01
  • 1970-01-01
  • 2013-05-09
相关资源
最近更新 更多