一入前端深似海,从此红尘是路人系列第一弹之浅析JavaScript继承

天涯浪子 提交于 2020-03-01 04:10:56

继承算是JavaScript中的一大难点也是必须掌握的知识点。接下来我会列举一些我们常见的继承并给出对应一些的code方便大家理解。

1.类式继承,既子类原型继承父类实例化。但是当我利用new关键字实例化子类的时候,当我改变子类继承到父类属性的时候,会污染到再次实例化的子类它所继承到的属性。具体如下

function SuperClass(){
	this.superValue = true;
	this.languages= ['JS','JAVA'];
}
SuperClass.prototype.getSuperValue = function(){
	return this.superValue;
}
function SubClass(){
	this.subValue = false;
}
SubClass.prototype = new SuperClass();
SubClass.prototype.getSubValue = function(){
	return this.subValue;
}
var sub = new SubClass();
console.log(sub.getSuperValue());
console.log(sub.getSubValue());
console.log(sub instanceof SuperClass); //true
console.log(sub instanceof SubClass);	//true
console.log(SubClass instanceof SuperClass); //false
console.log(SubClass.prototype instanceof SuperClass); //true
console.log(sub.languages) //['JS','JAVA']
sub.languages.push('HTML');
var sub1 = new SubClass();
console.log(sub1.languages); //['JS','JAVA','HTML']

2.构造函数继承,即在子类构造函数中利用call()更改作用域,将子类变量在父类中执行一遍,从而完成继承。该继承方式只能继承父类构造函数中的属性和方法,并不能直接继承到父类原型。

function SuperClass(id,books){
	this.id = id;
	this.books = ['JS','JAVA'];
}
SuperClass.prototype.showBooks = function(){
	return this.books;
}
function SubClass(id,books){
	SuperClass.call(this,id,books)
}
var sub = new SubClass();
sub.books.push('CSS');
console.log(sub.books); //['JS','JAVA','CSS']
var sub1 = new SubClass('superClass');
console.log(sub1.books); //['JS','JAVA']
console.log(sub.showBooks()); //Uncaught TypeError: sub.showBooks is not a function

3.组合继承,即将类式继承和构造函数继承进行功能的结合,形成一个更为优良的继承方式。该继承结合了类式继承和构造函数继承,即继承了父类原型,又继承了父类构造函数中的属性和方法。这样的好处就是在用new关键字实例化一个子类的时候改变该子类继承到的属性,不会影响下一个实例化的子类继承到的属性。但是该继承方式的缺点就是子类原型继承父类实例化的时候,也会跑一次父类的构造函数。

function SuperClass(name){
	this.name = name;
	this.books = ['JS','JAVA'];
}
SuperClass.prototype.getName = function(){
	return this.name;
}
function SubClass(name,time){
	SuperClass.call(this,name);
	this.time = time;
}
SubClass.prototype = new SuperClass('superClass');
SubClass.prototype.getTime = function(){
	return this.time;
}
var sub = new SubClass('superClass');
sub.books.push('CSS');
console.log(sub.books); //['JS','JAVA','CSS']
console.log(sub.getName()); //superClass
var sub1 = new SubClass('superClass');
console.log(sub1.books); //['JS','JAVA']

4.原型式继承,它是对类式继承的一个封装,在原型式继承中会声明一个过渡对象,为的就是创建要返回的新的实例化对象。这里由于F过渡类的构造函数没有内容,所以开销比较小,使用起来也比较方便。但还是有着类式继承一样的问题。

function inheritObject(o){
	//声明一个过渡函数
	function F(){}
	//过渡对象的原型继承父对象
	F.prototype = o;
	return new F();
}
var book = {
	name:'js book',
	alikeBook:['css book','html book']
}
var newBook = inheritObject(book);
newBook.name = 'ajax book';
newBook.alikeBook.push('xml book');
var otherBook = inheritObject(book);
otherBook.name = 'flash book';
otherBook.alikeBook.push('as book');
console.log(newBook.name); //ajax book
console.log(newBook.alikeBook); //['css book','html book','xml book','as book']
console.log(otherBook.name); //flash book
console.log(otherBook.alikeBook); //['css book','html book','xml book','as book']
console.log(book.name); //js book
console.log(book.alikeBook); //['css book','html book','xml book','as book']

5.寄生式继承,它是对原型继承的第二次封装,让新创建的对象不仅仅有父类中的属性和方法而且还可以添加新的属性和方法。

//声明基对象
function inheritObject(o){
	//声明一个过渡函数
	function F(){}
	//过渡对象的原型继承父对象
	F.prototype = o;
	return new F();
}
var book = {
	name:'js book',
	alikeBook:['css book','html book']
}
function createBook(obj){
	//通过原型继承方式创建对象
	var o = new inheritObject(obj);
	//拓展新对象
	o.getName = function(){
		console.log(this.name);
	};
	//返回拓展后的新对象
	return o;
}

6.寄生组合式继承,它将寄生式继承和构造函数继承进行结合,形成一个完美的继承方式。

/**
 * 寄生式继承 继承原型
 * 传递参数 subClass 子类
 * 传递参数 superClass 父类
 */
function inheritObject(o){
	//声明一个过渡函数
	function F(){}
	//过渡对象的原型继承父对象
	F.prototype = o;
	return new F();
}
function inheritPrototype(subClass,superClass){
	//复制一份父类的原型副本保存在变量
	var p = inheritObject(superClass.prototype);
	//修正因为重写子类原型导致子类的constructor指向父类
	p.constructor = subClass;
	//设置子类的原型
	subClass.prototype = p;
}
//定义父类
function SuperClass(name){
	this.name = name;
	this.colors = ['red','blue'];
}
//定义父类原型方法
SuperClass.prototype.getName = function(){
	return this.name;
}
//定义子类
function SubClass(name,time){
	//构造函数继承
	SuperClass.call(this,name);
	//子类新增属性
	this.time = time;
}
//寄生式继承父类原型
inheritPrototype(SubClass,SuperClass);
//子类新增原型方法
SubClass.prototype.getTime =function(){
	return this.time;
}
var test1 = new SubClass('js book',2014);
var test2 = new SubClass('csc book',2013);
test1.colors.push('black');
console.log(test1.colors); //['red','blue','black']
console.log(test2.colors); //['red','blue']
console.log(test2.getName());
console.log(test2.getTime());

至此,最终完美的寄生组合式继承便由此诞生了。

此篇文章只是我个人的一些见解,希望可以帮助到一些对于继承还比较模糊的小伙伴们。当然,如果有小伙伴觉着哪里有问题,欢迎指出,大家一起探讨交流。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!