【问题标题】:Javascript inheritance with concise prototype assignment syntax具有简洁原型赋值语法的 Javascript 继承
【发布时间】:2013-11-27 00:21:53
【问题描述】:

我使用这种 (prototype) 方法定义了两个 javascript 类:

function Parent () {
    this.a = 1;
}

Parent.prototype = {
    hello : function () {
        return "Hello I'm Parent!";
    },
    setA : function (a) {
        this.a = a;
    }
};

function Child () {
    this.b = 2;
}

Child.prototype = new Parent();
Child.prototype.constructor = Child;

Child.prototype = {
    hello : function () {
        return "Hello I'm Child!";
    },
    setB : function (b) {
        this.b = b;
    }
};

我使用这种技术是因为我认为标准语法过于冗长和稀疏:

Child.prototype.hello = function () {...};

Child.prototype.setB = function (b) {...};

这里的问题是我覆盖 Child.prototype(继承自Parent)失去了.setA() 方法(但正确地覆盖 .hello())。

合并两个原型是解决方案吗?怎么样?
这种方法会导致问题吗?

【问题讨论】:

  • 考虑继承:Child.prototype = Object.create(new Parent());
  • @Matías 您可以使用 Object.create 或辅助函数来防止在设置继承的原型部分时创建 Parent 实例,因此它应该是:Child.prototype = Object.create(Parent.prototype); 您和 OP 的方式Parent this.someting 的每个实例特定成员都放在 Child 原型上,并且(如果你做得正确的话)在创建 Child 实例时立即隐藏(Parent.apply(this, arguments) in Child body)。或者更糟;程序员假定 Child 具有 Parent 的实例成员,但没有意识到它们实际上是共享的。

标签: javascript oop inheritance


【解决方案1】:

合并两个原型是解决方案吗?

是的。

怎么做?

只需编写一个循环遍历对象字面量并将每个属性合并到原型中。

function inherit(Child, Parent, methods) {
    var p = Child.prototype = Object.create(Parent.prototype);
    p.constructor = Child;
    for (var m in methods)
        p[m] = methods[m];
    return p;
}
function Child () {
    Parent.call(this);
    this.b = 2;
}
inherit(Child, Parent, {
    hello : function () {
        return "Hello I'm Child!";
    },
    setB : function (b) {
        this.b = b;
    }
});

【讨论】:

  • 为了完整起见,如果 Child 实例想要将 this.a 赋值为 1 或以某种方式重新使用 Parent 初始化代码,那么在 Child 构造函数主体中你应该有 Parent.apply(this,arguments); 通常这部分被遗忘并且 OP 的示例代码不需要它,但我甚至看到 Crockford 抱怨父代码在继承时没有被重用,所以值得一提的是它可以被重用。
  • @HMR:感谢您的提醒,我忘记了盲目复制粘贴构造函数的时候。当然应该在那里!
【解决方案2】:

这是我从 pro javascript 设计模式中复制的示例

function extend (subClass, superClass) {
  var F = function () {};
  F.prototype = superClass.prototype;
  subClass.prototype = new F();
  subClass.prototype.constructor = subClass;

  subClass.superclass = superClass.prototype; 
  if (superClass.prototype.constructor === Object.prototype.constructor) {
    superClass.prototype.constructor = superClass;
  } // end if
} // end extend()

function Person (name) {
  this.name = name;
} // end Person()
Person.prototype.getName = function () {
  return this.name;
}; // end getName()

function Author (name, books) {
  Author.superclass.constructor.call(this, name); 
  this.books = books;
} // end Author()

extend(Author, Person);

Author.prototype.getBooks = function () {
  return this.books;
}; // end getBooks()
Author.prototype.getName = function () {
  var name = Author.superclass.getName.call(this);
  return name + " , author of " + this.getBooks();
}; // end getName()

var a = new Author("xxx", "xxx");
console.log(a.getName()); // xxx , author of xxx

作者列举了三种实现继承的方式:基于类、基于原型和基于增强。

您可以阅读代码,也可以阅读本书..

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 2013-02-09
    • 2013-10-02
    • 2010-09-28
    • 2018-02-21
    相关资源
    最近更新 更多