这两种类型的继承有什么区别?

What is the difference between the two types of inheritance?

本文关键字:什么 区别 继承 两种 类型      更新时间:2023-09-26

说明两种继承类型的区别?

function inherit(c,p){
    var F =function(){}
    F.prototype=p.prototype;
    c.prototype=new F();
}

function inherit(c,p){
    c.prototype=p.prototype;
}

如果有的话,它们的优缺点是什么?

在第二个例子中,cp最终都使用了相同的对象作为它们的prototype属性。因此,向该对象添加某些内容会影响使用new cnew p创建的实例,因为这些实例从函数上的prototype属性获得其底层原型。这是一个问题,孩子不应该像那样影响父母的实例。

因此,例如,使用第二个,我们有这个问题:

function Parent() {
}
function Child() {
}
inherit(Child, Parent);
Parent.prototype.question = "Life, the Universe, and Everything";
Child.prototype.answer = 42;
var par = new Parent();
var ch = new Child();
console.log(par.question); // "Life, the Universe, and Everything"
console.log(ch.question);  // "Life, the Universe, and Everything"
console.log(par.answer);   // 42 <=== WRONG, Parent instances don't have the property
console.log(ch.answer);    // 42

上面的代码在内存中创建了这种情况(让我们使用一个名为__proto__的属性来表示对象的底层原型;这就是即将到来的ES6规范所做的):

<>之前第二个:错了+-----------------+|函数父级|+-----------------+ +---------------+| prototype |----+++——>| Object |+-----------------+ ||| +---------------+||| |问题:……|+------------+ ||| |答案:42 ||父级| ||| +---------------++------------+ |||| __proto__ |---------+||+------------+ ||||+-----------------+ ||函数子函数||+-----------------+ |||原型|-----+|+-----------------+ ||+-----------+ |孩子ch | |+-----------+ || __proto__ |------------++-----------+之前

对于第一个c.prototype是一个以p.prototype作为其底层原型的新对象。向c.prototype 添加内容不会影响用new p创建的实例,只会影响用new c创建的实例。但是向p.prototype添加东西会影响两者,如果c意味着继承p,这是有道理的。

function Parent() {
}
function Child() {
}
inherit(Child, Parent);
Parent.prototype.question = "Life, the Universe, and Everything";
Child.prototype.answer = 42;
var par = new Parent();
var ch = new Child();
console.log(par.question); // "Life, the Universe, and Everything"
console.log(ch.question);  // "Life, the Universe, and Everything"
console.log(par.answer);   // undefined, Parent instances don't have the property
console.log(ch.answer);    // 42

在内存中设置:

<>之前第一个+-----------------+|函数父级|+-----------------+ +---------------+|原型 |----+----& gt; |对象 |& lt; - ++-----------------+ | +---------------+ |问题:……| |+------------+ | +---------------+ |父级参数| | |+------------+ | || __proto__ |---------+ |+------------+ ||+-----------------+ |函数子函数+-----------------+ +---------------+ ||原型 |------+--& gt; |对象 | |+-----------------+ | +---------------+ || | __proto__ |——++-----------+ | |答案:42 ||孩子ch | | +---------------++-----------+ || __proto__ |------------++-----------+之前

如果有的话,它们的优缺点是什么?

第二个实际上是错误的。: -)


边注:在支持es5的环境中,第一个可以更简单:
function inherit(c,p){
    c.prototype = Object.create(p.prototype);
}

旁注2:为了更彻底,第一个应该是这样的:

function inherit(c,p){
    var F =function(){}
    F.prototype=p.prototype;
    c.prototype=new F();
    c.prototype.constructor = c;
}

或:

function inherit(c,p){
    c.prototype = Object.create(p.prototype);
    c.prototype.constructor = c;
}

Function对象的prototype属性引用的对象的constructor属性应该指向该函数。这就是规范中设置函数的方式,尽管实际上并没有使用 constructor属性。然而,有些人可能有使用它的代码,并期望规范的设置在那里。