欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-15 23:29:54
...

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

继承的目的:

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

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

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

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

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

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

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

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

       废话不多说直接上图:

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

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

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

JavaScript关于完美继承的问题(个人认为:网上绝大多数的说法都不够完美)
图1
JavaScript关于完美继承的问题(个人认为:网上绝大多数的说法都不够完美)
图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());
//========第二级继承========
相关标签: JS