1

我正在阅读 kangax 关于如何 ECMAScript 5 仍然不允许子类化数组的博客。在这里,他使用了与正常原型构造不同的子类化方法

BaseClass.prototype = new Superclass();

他正在做的是:

function clone(obj) {
  function F() { }
  F.prototype = obj;
  return new F();
}

然后像这样设置继承:

function Child() { }
Child.prototype = clone(Parent.prototype);

有人能解释一下这种两部分继承的方法,以及它比上面简单的单线方法有什么好处吗?

编辑:我从评论中了解到,现在有一个标准Object.create()基本上解决了与方法相同的目的,clone()但是这种实现如何clone()工作?

4

2 回答 2

0

这是一个有趣的问题。您提供的一段代码(克隆函数)被 Douglas Crockford 称为“原型继承”,并在他的网站上的这篇文章中进行了描述。这种模式变得流行并在ECMA 脚本 5 中形式化为 Object.create(),如果您查看 object create 的规范,它与 Crockford 函数的规范完全相同。它是这样使用的:

var Animal = {
    species: "mammal",
    noises: function () {
        console.log("makes noises")
    },
    actions: ["roll back", "jump up"]
}

var Cat = Object.create(Animal);
Cat.name = "blacky"
Cat.miau = function () {
    console.log("miau miau");
}

Crockford 也称这种差异继承,因为在定义子类的新属性时,您只需指定子类和超类之间的差异。Cat 现在拥有自己的属性“name”和自己的方法“miau”。

我认为这样做的主要问题是您仍然在实例之间共享引用值,例如数组。

如果我们这样做:

var Cat2 = Object.create(Animal);
Cat2.actions.push("bite Henry");
Cat2.actions
["roll back", "jump up", "bite Henry"]
Cat.actions
["roll back", "jump up", "bite Henry"]

但至少实例原始属性不共享,这很好。

Cat2.name
undefined
Cat.name
"blacky"
于 2013-07-13T10:20:16.777 回答
0

要演示为什么要使用 Object.create 或辅助函数来设置继承原型,请参见以下代码:

function Hamster(name){
  if(name ===  undefined){
    throw new Exception("Name cannot be undefined");
  }
  this.name=name;
};

function RussionMini=function(name){
  Hamster.apply(this,arguments);
};
RussionMini.prototype=new Hamster();//throws Error

您可以这样做RussionMini.prototpe=new Hamster("dummyvalue");,但是如果需要传递一个在您声明对象时不可用的值(如 DOM 元素),该怎么办。您仍然可以传递一个 dummy,但它会使您的代码更复杂,并且在重构时更容易中断。

这两个例子都没有修复prototype.constructor,所以this.constructor会指向错误的函数(当你使用Object.create(Parent.prototype)时也会发生;`

更多关于继承、覆盖函数和使用构造函数的原型可以在这里找到:原型继承 - 编写

于 2013-07-13T13:08:22.453 回答