由于Son和Father的原型对象指向同一对象,这样就导致了不管是修改Father原型对象还是Son原型对象的属性或方法,另一个的原型对象也会跟着修改

发布时间 2023-11-16 14:07:02作者: 龙陌

执行以下程序,输出结果为()

function Father(age){
    this.age = age
}
function Son(age){
    Father.call(this);
}
Son.prototype = Father.prototype;
Father.prototype.getAge = function(){console.log(40);}
Son.prototype.getAge = function(){console.log(18);}
var father = new Father(40);
var son = new Son(18);
son.getAge();
father.getAge();

A
18 18

B
40 40

C
18 40

D
18 undefined

正确答案:A

本题属于ES5继承中的共享原型,由于Son和Father的原型对象指向同一对象,这样就导致了不管是修改Father原型对象还是Son原型对象的属性或方法,另一个的原型对象也会跟着修改。
由于getAge()方法均定义在原型对象,后定义的getAge()方法会覆盖先定义的getAge(),所以最终输出结果均是18,A选项正确。

function Father(age) { //此时Father.prototype = { constructor: function Father(){}}
    this.age = age
}
function Son(age) { //此时Son.prototype = { constructor: function Son(){}}
    Father.call(this);
}

Son.prototype = Father.prototype;
//此时Son.prototype = { constructor: function Father(){}}   
//此时Father.prototype = { constructor: function Father(){}}
//现在,Son和Father的prototype指向同一个对象,也就是指向堆里的同一个地址


Father.prototype.getAge = function () { console.log(40) },//堆里加一个getAge属性
//此时:
// Father.prototype = {
//     constructor: function Father(){}
//     getAge: function(){console.log(40);}
// }
//特别注意,因为Son和Father的prototype指向同一个对象(堆里同一个地址),所以
// Son.prototype = {
//     constructor: function Father(){}
//     getAge: function(){console.log(40);}
// }

Son.prototype.getAge = function () { console.log(18) };
//此时:
// Son.prototype = {
//     constructor: function Father(){}
//     getAge: function(){console.log(18);}
// }
//因为Son和Father的prototype指向同一个对象(堆里同一个地址),所以
// Father.prototype = {
//     constructor: function Father(){}
//     getAge: function(){console.log(18);}
// }


var father = new Father(40); // father = { age: 40 } 
var son = new Son(18); //如果构造函数Son里没有Father.call(this);  那么此时 son = {}
//但是,构造函数Son里有Father.call(this);  然后 son = { age: undefined } (暂时不太明白这是为什么)

//以上结束后father = { age: 40 } 
//以上结束后son = { age: undefined } 


father.getAge(); //father里只有一个age,没有getAge方法,去原型Father.prototype里找, 执行函数console.log(18)
son.getAge();//son里只有一个age,没有getAge方法,去原型Son.prototype里找, 执行函数console.log(18)

//本题跟传入的age没有关系,因为getAge方法里没有任何对age的处理,只是执行一个console.log()

首先代码使用了组合继承,

然后:
Father.prototype.getAge = function(){console.log(40);}
Son.prototype.getAge = function(){console.log(18);}

这两个表达式中Son.prototype.getAge 会将 Father 构造函数的 getAge 原型方法替换掉
再然后这里的Son.prototype = Father.prototype;实际并不会生效,因为当执行到 var son = new Son(18) 表达式时,Son.prototype 会自动被赋值为 Father 构造函数的实例实现继承;

因此最后
son.getAge();
father.getAge();
调用的实际上都是

function(){console.log(18);}这个方法