今天我和大家一起复习学习一下javascript中的原型链和继承。
- 原型链
下面用一张图带大家看清楚原型链
构造函数的原型有一个constructor属性指向构造函数本身,实例的隐式原型_proto_指向构造函数的原型。
Person.prototype.constructor === Person //true
person._proto_ === Person.prototype // true
- 继承(原型继承、构造函数继承、组合继承,寄生式继承,寄生组合式继承)
- 原型继承
// 父类
function Parent(){}
// 子类
function Son(){}
// 子类继承父类
Son.prototype = new Parent()
// 弊端:父类引用类型数据, 将会被子类的实例共享。
- 构造函数继承
// 父类
function Parent(){}
// 子类
function Son(){
Parent.call(this);
}
// 实质: 父类构造函数执行赋给子类的this。复制一份
// 弊端: 无法继承父类在原型prototype上的属性
- 组合继承
// 父类
function Parent(){}
// 子类
function Son(){
Parent.call(this);
}
Son.prototype = new Parent()
// 实质:构造函数继承,原型继承。
// 弊端: 构造函数Parent会被执行2次
- 寄生式继承
function createAnother(original){
var clone = Object(original);//创建一个新对象,original的副本
clone.sayName = function(){ //对象的增强,添加额外的方法
alert('hi');
}
return clone;
}
var parent= {
name:'小明',
friends:['小红','小强']
}
// 应用场景: 考虑对象而不是自己定义类型和构造函数的情况下,寄生式继承是一种有用的模式
// 实质:创建一个新的对象,并为他添加新的方法和属性。
// 弊端:但无法做到函数的复用
- 寄生组合式继承
function inheritPrototype(son,parent){
var prototype = Object.create(parent.prototype);//ES5中创建对象副本的方法
prototype.constructor = son; //弥补重写原型失去的默认constructor属性
son.prototype = prototype;
}
}
function Parent(){}
function Son(name){
Parent.call(this);
}
inheritPrototype(Son, Parent)
// 实质:构造函数继承,原型继承。
// 优点:寄生组合式继承解决了组合式继承调用两次超类构造函数的问题
- es6中的继承
class Point {}
class ColorPoint extends Point {
constructor() {
super(); // 调用父类的constructor()
}
}
// 1.该类通过extends关键字实现继承
// 2. 必须通过在constructor调用super方法得到子类的this对象,否则子类无法使用this
// 3. es5的继承:实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this)))
// 4. es6继承:实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。
如有错误,欢迎留言指正!