回顾知识:构造函数会有一个原型对象属性(prototype),原型对象有一个属性construct指回构造函数,而实例包含一个指向原型对象的内部指针(__ proto__)。
原型链继承
概念:让原型对象等于另一个类型的实例,另一个类型的实例的原型又是指向原型对象,这样层层递进,实现了继承。
function Father(){
this.name = "hzs";
this.age = 22;
this.colors = ['red', 'green', 'purple'];
}
Father.prototype.getPersonValue = function(){
return this.name
}
function Children(){
this.name = "yqe"
}
// 继承了父类
Children.prototype = new Father();
// 在子类增加新的属性,要放在替换原型之后去做
Children.prototype.getChildrenValue = function(){
return this.age;
}
Children.prototype.text = "课本";
let chil = new Children();
et chilT = new Children();
console.log(chil.getChildrenValue()); // 22
chil.colors.push("black");
console.log(chil.colors); //["red", "green", "purple", "black"]
console.log(chilT.colors); //["red", "green", "purple", "black"]
缺陷:(1)引用类型值的原型共享给所有继承,值会受到它们的影响;(2)创建子类型的实例时,不能向超类型函数传递参数
借用构造函数
概念,在子类型的构造函数的内部调用超类型构造函数。
function Father(name) {
this.colors = ['red', 'green', 'purple'];
this.name = name;
}
// 用call方法在子类型构造函数中调用超类型的构造函数。
function Children() {
this.name = "yqe"
Father.call(this, 'huangzishuan');
}
console.log(chil.colors); //["red", "green", "purple", "black"]
console.log(chilT.colors); //["red", "green", "purple"]
结果:通过使用call方法,实际是在将要创建children实例的环境下调用Father构造函数,这样一来,就会在新Children对象上执行Father函数中定义的所有对象初始化代码。结果,每个Children的实例就有自己的colors属性的副本了。
缺陷:父类原型,子类访问不了
组合继承(原型链和借用构造函数结合体)
function Father() {
this.colors = ['red', 'green', 'purple'];
}
Father.prototype.sex = "男";
Father.prototype.remove = function() {
console.log(
}
function Children() {
this.name = "yqe"
Father.call(this);
}
// 继承了父类
Children.prototype = new Father();
Children.prototype.constructor = Children;
let chil = new Children();
let chilT = new Children();
chil.colors.push("black");
console.log(chil.colors);//["red", "green", "purple", "black"]
console.log(chilT.colors);//["red", "green", "purple"]
chil.remove();//"father原型的方法"
结果:组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点。实现父类引用类型不会被实例干扰,和子类可以传参给父类。
缺陷:需要调用两次父类构造函数
原型式继承
概念:借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
function object(o) {
function F(){}
F.prototype = o;
return new F();
}
注释:ES5新增Object.create()方法规范了原型式继承,第一个参数用作新对象原型的对象和(可选)一个为新对象定义额外属性的对象。在传入一个参数时,其跟object()方法相同。
举个栗子:
var person = {
name: "NICK",
friends: ["sendy", "yike"];
}
var anotherPerson = Object.create(person, {
name: {
value: "Grek";
}
})
console.log(anotherPerson.name); //Grek
缺陷:包含引用类型值得属性始终都会共享相应的值
寄生式继承
概念:与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象
举个栗子:
function createAnother(original){
var clone = object(original);//通过调用函数创建一个对象
clone.sayHi = function() {
console.log("hi");
}
return clone;
}
var person = {
name: "nick",
age: 15
}
var anotherPerson = createAnother(person);
another.sayHi(); //hi
缺陷:函数不可复用
寄生组合继承(原型式和寄生的结合体)
function inheritPrototype(children, father) {
let prototype = Object(father.prototype);
prototype.constructor = children;
children.prototype = prototype;
}
function Father() {
this.colors = ['red', 'green', 'purple'];
}
Father.prototype.sex = "男";
Father.prototype.remove = function() {
console.log(father原型的方法);
}
function Children() {
this.name = "yqe"
Father.call(this);
}
inheritPrototype(Children, Father);
// 继承了父类
let chil = new Children();
let chilT = new Children();
chil.colors.push("black");
console.log(chil.colors);//["red", "green", "purple", "black"]
console.log(chilT.colors);//["red", "green", "purple"]
chil.remove();//"father原型的方法"
结果:这个例子体现在只调用了一次Father构造函数,同时原型链还能保持不变。