JavaScript关于完美继承的问题(个人认为:网上绝大多数的说法都不够完美)

(文章纯粹自己的理解,如果有问题请留言或私信)

继承的目的:

1) 复用方法(父的方法)
2) 有权添加/重写父的方法

3)不允许添加/重写父方法/属性的时候污染到父类

通常被认为是完美继承的就是:寄生组合继承

1.为什么我认为他们不够完美呢?

       这里解释一下,不是觉得寄生组合继承不够完美,而是大多数都没搞懂什么是寄生组合继承。

       虽然他们的结果没什么问题,达到的效果很不错。但是,作为处女座的我,依旧对他们的代码感到一股强烈的违和感。要么污染了父类,要么结构混乱,要么程序复杂,要么多次继承的时候麻烦。

2.接下来我会讲解一下我认为完美的继承:

       其实这个继承的方法不用我们自己去想,JS已经提供了。

       废话不多说直接上图:

图中有一点不好表达,我说明一下:

       图中Woman构造器的prototype对象包含了一个person实例对象,但是我要表达的是Woman构造器的prototype对象包含了person实例对象的所有内容。

       还有就是“指向”的线条类似指针的效果,通过constructor能够访问到对于的构造器。

图1
图2

 

其中:

       Person、Woman、YellowMan都是function出来的构造器对象(也是函数)

       而YellowMan继承了Woman,Woman继承了Person,而Person是初代。

       这里说明一下,prototype属性和__proto__属性都是对象,而且他们的所有者都能够直接访问其内部的属性,而且能够像套娃一样访问,这也是我们继承的理论基础,只不过优先级并不一样,所有者自己直属属性>__proto__内部>prototype内部。

      还有一点就是构造器实例化的时候,实例的__proto__属性是和构造器的prototype属性相同的,都指向相同的对象数据类型的一块内存。同时,实例的过程实际上还通过构造器的name属性找到了构造器函数,进行了一次call函数,就完成了属性的实例化。

       图2解释了部分Object构造器对象和Function构造器对象的关系,对象o和对象f是没有名字的两个对象,但是在整个结构里很重要所以一起列出来。

      从图1里我们应该能看到这种继承看起来就很舒服,至于“指向”的那条线只是为了跟随初代的脚步,作用大概就是在整个链路里保存构造器。

 

最后,按照图示逻辑写代码如下(输出结果可以自行实验,我得到的结果很完美):

(补充一句:call函数用不用都行。我更倾向于不使用call,因为每次继承都要call一下实在不爽,而且数据就结构和初代继承会不一样,再有一点就是变量的优先级容易发生混淆。call函数如果在自定义属性的后面,那么你自定义的属性将没法覆盖继承来的值,渣渣)


//========公共继承用函数========
//继承父类
function myInherit(son,father){
  //父类的实例作为子类的原型
  son.prototype = new father();
  //修复构造函数指向问题
  son.prototype.constructor = son;
}
//========公共继承用函数========

//========父类========
function Person(name,age){
  this.name = name || 'wangxiao';
  this.age = age || 27;
}
//父类方法
Person.prototype.eat = function(){
  return this.name + this.age + 'eat sleep';
}
//========父类========


//========第一级继承========
function Woman(){
	this.gender="female";
	this.age=38;//覆盖
}
//使用公共的继承函数
myInherit(Woman,Person);
//添加方法,如果要在构造器外添加,一定要放在继承函数后面,防止覆盖
Woman.prototype.birth=function(){
  return this.name + this.age + this.gender + 'eat sleep pregnant';
}
//实例化
let womanObj = new Woman();
//输出结果
console.dir(womanObj.name);
console.dir(womanObj.age);
console.dir(womanObj.gender);
console.dir(womanObj.birth());
//========第一级继承========

//========第二级继承========
function YellowWoman(){
	this.color="yellow";
	this.age=40;//覆盖
}
//使用公共的继承函数
myInherit(YellowWoman,Woman);
//添加方法,如果要在构造器外添加,一定要放在继承函数后面,防止覆盖
YellowWoman.prototype.sleep=function(){
  return this.name + this.age + this.gender + this.color + 'eat sleep pregnant yellow';
}
//实例化
let yellowWomanObj = new YellowWoman();
//输出结果
console.dir(yellowWomanObj.name);
console.dir(yellowWomanObj.age);
console.dir(yellowWomanObj.gender);
console.dir(yellowWomanObj.color);
console.dir(yellowWomanObj.sleep());
//========第二级继承========
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值