JavaScript实现继承的几种方式

继承

原型链

基本思想:让原型对象等于另一个类型的实例。

function Parents(){
	this.name = 'father';
}
Parents.prototype.getName = function(){
	return this.name;
}

function Sun(){
	this.SunName = 'xiaoming';
}

Sun.prototype = new Parents();
Sun.prototype.getSunName = function(){
	return this.SunName;
}
var child = new Sun();
console.log(child.getName());  //father

这里写图片描述
所有引用类型默认都继承了object
原型链实现继承的问题:
包含引用类型的原型,会被所有实例共享。

借用构造函数(伪造对象或经典继承)

解决了原型中包含引用类型所带来的问题。
思想:在子类型的内部,调用超类型的构造函数

function SuperType(){
	this.colors = ["red", "blue", "green"];
}
function SubType(){
	//继承了SuperType
	SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green"

利用call或apply在要创建subtype实例的环境下调用了supertype的构造函数,这样subtype的实例都会有自己的引用类型的值。
问题:
存在和构造函数模式一样的问题——方法都会在构造函数中定义,无法复用函数。

组合继承(伪经典继承)

将原型链和借用构造函数组合到一起,发挥二者长处的继承模式。

function Parents(name){
	this.name = name;
	this.hobit = ['buy','play','eat'];
}
Parents.prototype.sayName = function (){
	return this.name;
}
function Sun(name) {
	Parents.call(this,name);  //第二次调用Parents()
	this.age = 18;
}

Sun.prototype = new Parents();  //第一次调用Parents()
Sun.constructor = Sun;
Sun.prototype.sayAge = function(){
	return this.age;
}

var child1 = new Sun('xiaoming');
var child2 = new Sun('xiaohong');
child1.hobit.push('drink');
console.log(child1.hobit);   //["buy", "play", "eat", "drink"]
console.log(child2.hobit);   //["buy", "play", "eat"]

console.log(child1.sayName());   //xiaoming
console.log(child2.sayName());   //xiaohong

组合继承是JavaScript最常用的继承模式,但会调用两次超类型构造函数。

原型式继承
function object(o){
	function F(){}
	F.prototype = o;
	return new F();
}
var person = {
	name: "Nicholas",
	friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
  • 有一个对象作为另一个对象的基础
    Object.create()方法
var person = {
	name: "Nicholas",
	friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = Object.create(person, {
	name: {
		value: "Greg"
}
});
alert(anotherPerson.name); //"Greg"

如果只想让创建的对象和另一个对象保持类似,原型式就够了。
引用类型的值会被共享。

寄生式继承

创建一个仅用于封装继承过程的函数,该函数在内部已某种方式来增强这个对象,最后再像真的是他做了所有工作一样返回对象。

function createAnother(original){
	var clone = object(original); //通过调用函数创建一个新对象
	clone.sayHi = function(){ //以某种方式来增强这个对象
		alert("hi");
	};
	return clone; //返回这个对象
}
var person = {
	name: "Nicholas",
	friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"

object函数不是唯一的,任何能返回新对象的函数都使用于这个模式。
这种模式不能做到函数的复用,与构造函数模式类似。

寄生组合式继承

可以解决组合继承调用两次超类型的问题。
基本思路:
子类型的原型不调用超类型的构造函数,调用超类型的一个副本。
使用寄生式继承来继承超类型的原型。

function inheritPrototype(subType, superType){
	var prototype = object(superType.prototype); //创建对象
	prototype.constructor = subType; //增强对象
	subType.prototype = prototype; //指定对象
}

接受两个参数,子类型构造函数,超类型构造函数

  1. 创建超类型原型的一个副本
  2. 为创建的副本添加constructor属性,从而弥补重写原型而失去的constructor属性
  3. 将新创建的对象赋值给子类型的原型
function SuperType(name){
	this.name = name;
	this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
	alert(this.name);
};
function SubType(name, age){
	SuperType.call(this, name);
	this.age = age;
}

inheritPrototype(SubType, SuperType);  //和组合继承不同的地方

SubType.prototype.sayAge = function(){
	alert(this.age);
};

开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值