6种对象继承方式
1、原型链继承
// 通过将自己的原型继承于另外一个构造函数创建出来的对象,将被继承的对象中的所有属性都存在于__proto__属性中.
// 缺点:
// 1)原型链继承多个实例的引用属性指向相同,改变一个会影响另一个实例的属性.
// 如果是引用类型的,继承的是地址,那么子原型中的引用地址和父对象中的引用地址相同
// 2)不能传递参数
// 因为是原型上继承所以不能传递参数
// 3)继承单一
function Father(){
this.FatherName = "father's 构造函数";
}
Father.prototype.age = 40;
function Son(){
this.SonNname = "Son's 构造函数";
}
//Son的原型继承Father创建出来的对象,相当于继承了Father的全部内容,同时全部都存在Son__proto__属性里
Son.prototype = new Father();
Son.prototype.getSubValue = false;
Son.prototype.age1 = 20;
var example =new Son();
console.log(example.age);
2、借用构造函数继承
使用call()和apply()将父类构造函数引入到子类函数,使用父类的构造函数来增强子类的实例,等同于复制父类的实例给子类
这种方法就是通过call()apply(),完完全全复制了一份给子类,所以子类的任何操作都不会影响到父类
缺点:
只能继承父类的实例属性和方法,不能继承到原型中的内容
无法实现构造函数的复用,每个子类都有父类实例函数的副本,影响性能,代码会臃肿
function Father(name){
this.name = name;
this.colors = ["red"];
}
Father.prototype.sex = 1;
function Son(name,age){
Father.call(this,name);//利用call改变this的指向将this指向父类中的name,这样就把Father中方法给引入到子类中了
this.age = age;
}
var obj = new Son("张三",25);
obj.colors.push("write"); //引用类型的也不会改变父类中的内容
console.log(obj.colors);// [red write]
var obj2= new Son("jike",10);
console.log(obj2.colors);//[red]
console.log(obj2.sex);//undefined 无法继承到父类原型中的内容
3,组合继承
// 将原型链继承和构造函数继承这两种模式的有点组合在一起,通过调用父类构造,继承父类的属性并保留传参,然后通过将父类实例作为子类原型,实现函数复用.
缺点:
父类中的实例属性,方法即存在子类的实例中,也存在于子类的原型中,占内存
同时也继承了以上的优点和缺点,
对于引用类型的数据,子类实例对其操作会影响到父类中的
优点:既可以继承到父类的原型中的方法,也可以传参
function Father(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
Father.prototype.sayName=function(){
console.log(this.name);
}
function Son(name,age){
//构造函数继承
Father.call(this,name);
this.age = age;
}
//原型链继承
Son.prototype = new Father();
var obj = new Son("jike",25);
console.log(obj);
obj.sayName();//jike 可以调用父类的原型上的方法
obj.colors.push("write");
console.log(obj.colors);// ["red", "blue", "green", "write"]
var obj2 = new Son("mike",30);
console.log(obj.colors);//["red", "blue", "green", "write"]
4.原型式继承
// 重点:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了可以随意增添属性的实力或者对象. object.create()就是这个原理
// 特点:类似于复制一个对象,用函数来包装
// 缺点:1.所有实例都会继承原型上的属性,方法
// 2.无法实现复用.(新实例的属性都是后面添加)
function content(obj){ //封装一个函数,用来输出对象和承载继承的原型
function F(){ //创建一个构造函数,同时会有一个原型产生
}
F.prototype=obj; //使其构造函数的原型继承于obj obj为传入的参数,是一个对象
return new F(); //返回利用这个函数创造的一个新实例
}
var obj = new Object();//obj为一个对象
obj.name = "jike";//给obj对象一个属性
obj.colors = ["red","blue"];
obj.__proto__.age=[1,2,3,4];
var obj2 = content(obj);//调用继承函数,并将要继承的对象传入到函数里面
console.log(obj);
obj2.colors.push("write");
obj2.age.push(10);
console.log(obj2);
console.log(obj2.age);
console.log(obj);
var obj3 = Object.create(obj);
console.log(obj3);
var obj4 = content(obj);
console.log(obj4);
// 和原型链继承一样,同样是将自身的对象原型继承一个完整的对象,也可以说是将一个对象作为自身的原型对象,对于引用类型的数据一样继承的是引用地址,那么一个子实例对引用类型的数据进行操作的话,所有实例都会受到影响.