最近在看阮老大的对象继承,Javascript面向对象编程(二):构造函数的继承
,但是我自己跑了下代码,发现几个问题,不知道是哪里不对。三个问题:
1、构造函数apply方式
//打印object
function logObj(obj) {
console.log('new OBJECT LOG-------------------------------');
for(var prop in obj) {
console.log(`${prop} == ${obj[prop]}`);
}
}
function Person(name, sex) {
this.name = name;
this.sex = sex;
this.fav = 'read';
}
Person.prototype.say = function() { //公用方法
console.log(`I'm ${this.name},and my sex is ${this.sex}`);
}
function People(name,sex,nation){
Person.apply(this,arguments);
this.nation = nation;
}
var me = new People('li','man','China');
console.log(me);
me.say();//报错未定义
apply构造函数继承的方式,拿不到person的say共有方法.
2、另外一种继承方式,
function People(nation) {
this.nation = nation;
}
People.prototype = new Person();
console.log(People.prototype.constructor);
People.prototype.constructor = People;
var me = new People('China');
logObj(me);
通过继承父类实例倒是可以拿到属性和公用方法,但是父类属性是undefined.子类实例构造函数参数中,又该如何重修改父类的属性呢,比如name,难道只能是通过me.name来修改吗
3、直接继承原型
function extend(Child, Parent) {
var F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
function People(nation) {
this.nation = nation;
}
extend(People, Person);
var he = new People('China');
logObj(he);
console.log(he.name);//undefined
console.log(he.fav); //undefined
发现这种继承方式可以拿到共有方法say,但是继承不到父级Class的属性name和sex,fav。
感觉每个都不对啊,后面还有个拷贝继承,添加新属性的时候都报错了,说明原型链上就没有啊
//深拷贝
var Chinese = {
nation: '中国',
fav: 'read'
};
var Doctor = {
career: '医生'
}
function deepCopy(p, c) {
var c = c || {};
for(var i in p) {
if(typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
}
var Doctor = deepCopy(Chinese);
Chinese.birthPlaces = ['北京', '上海', '香港'];
Doctor.birthPlaces.push('厦门'); //报错
logObj(Chinese);
logObj(Doctor);
new Person()
内部首先是创建了一个Object实例person {},this指向的就是这个{},最后return 这个person 实例;单独执行Person时,这个this没有意义,严格模式下报错,非严格模式下指向window;
Person.apply(this,arguments)
只是执行Person这个方法,并且将Person方法内部的this替换为People方法中的this,相当于复制了这种方式构造函数的prototype相互独立,两个类型并没有继承关系,无法让 instanceof 为 true;
为了弥补这一缺点,就要引入第二张方法,让People.prototype指向Person实例。
两个方法结合应该是这样:
这样就继承了父类原型上的方法,而属性则是自己拷贝过来的。
如果我们完全重写自己的构造函数,并只继承父类的方法,则适合用第三种方法(比如说父类中的属性都是私有的情况);
拷贝继承说是继承,其实就是个对象复制,跟继承完全没啥关系了;
js中的继承都是通过原型链实现的,个人感觉这种实现方式有点“虚”,你有兴趣可以对比一下虚表继承。