1.原型链继承:
function Super() {
this.property = true;
this.colors = ["red", "green"];
}
Super.prototype.getSuperValue = function() {
return this.property;
}
function Sub() {
this.property = false;
}
Sub.prototype = new Super();
Sub.prototype.getSubValue = function() { // 新增
return this.property;
}
Sub.prototype.getSuperValue = function() { // 重写
return "hehe";
}
var instance = new Sub();
alert(instance.getSuperValue()); // hehe
var superInstance = new Super();
superInstance.getSuperValue();
var sub1 = new Sub();
sub1.colors.push("blue");
var sub2 = new Sub();
alert("colors:"+sub2.colors); // ["red", "green", "blue"]
缺点:1.包含引用类型值的原型属性会被所有实例共享;2.在创建子类型的实例时,不能向父类构造函数传递参数(实际上,应该说是没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数);
2.借用构造函数
function Super() {
this.colors = ["red", "green"];
}
function Sub() {
Super.call(this);
}
var sub1 = new Sub();
sub1.colors.push("blue");
var sub2 = new Sub();
sub2.colors // ["red", "green"]
思想:在子类型构造函数内部调用超类型构造函数
缺点:多个实例的方法不能够实现复用
3.组合继承:
思想:使用原型链实现对原型属性和方法的继承,而通过对借用构造函数来实现对实例属性的继承
function Super(name) {
this.name = name;
this.colors = ["red", "green"];
}
Super.prototype.sayName = function() {
alert(this.name);
}
function Sub(name, age) {
Super.call(this, name);
this.age = age;
}
Sub.prototype = new Super();
Sub.prototype.sayAge = function() {
alert(this.age);
}
var sub1 = new Sub("lucy", 20);
sub1.colors.push("blue");
alert(sub1.colors); // ["red", "green", "blue"]
sub1.sayName(); // lucy
sub1.sayAge(); // age
var sub2 = new Sub("lily", 18);
alert(sub2.colors); ["red", "green"]
sub2.sayName(); // lily
sub2.sayAge(); // 18
这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性
组合继承成为JavaScript最常用的继承方式
4.原型式继承
思想:借助原型,可以基于已有的对象创建新对象
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var person = {
name: "lucy",
friends: ["zhangsan", "lisi", "wangerxiao"]
};
var o1 = object(person);
o1.name = "lily";
o1.friends.push("haola");
var o2 = object(person);
o2.name = "Linda";
o1.friends.push("haha");
alert(person.name); // lucy
alert(o2.friends); // ["zhangsan", "lisi", "wangerxiao", "haola", "haha"]
alert(person.friends); // ["zhangsan", "lisi", "wangerxiao", "haola", "haha"]
var person = {
name: "lucy",
friends: ["zhangsan", "lisi", "wangerxiao"]
};
var o1 = Object.create(person);
o1.name = "hah";
person.name
原型式继承:可以不必在预先定义构造函数的情况下实现继承。其本质是执行给定对象的浅复制,而复制得到的副本还可以得到进一步的改造。
5.寄生式继承
function createAnthor(original) {
var clone = object(original);
clone.sayHi = function() {
alert("hi")
}
return clone;
}
寄生式继承:与原型式继承非常相似,也是基于某个对象,某些信息创建一个对象,然后增强对象,最后返回对象
6.寄生组合式继承
组合式继承的缺点是调用了两次超类型构造函数,code:
function Super(name) {
this.name = name;
this.colors = ["red", "green"];
}
Super.prototype.sayName = function() {
alert(this.name);
}
function Sub(name, age) {
Super.call(this, name); // 第二次
this.age = age;
}
Sub.prototype.sayAge = function() {
alert(this.age);
}
Sub.prototype = new Super(); // 第一次
var instance = new Sub("lucy", 20);
instance.sayName();
寄生组合式继承就是为了弥补组合式继承中多次调用超类型构造函数的低效率问题而诞生的
寄生组合式继承:不必为了指定子类型的原型,而调用超类型的构造函数,我们所需的为非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承,来继承超类型的原型,然后再将结果指定给子类型的原型。这样,便使得超类型构造函数的属性成为了Sub的实例属性,不会再在子类型的原型中出现一次
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function inheritPrototype(subType, superType) {
var prototype = object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function Super(name) {
this.name = name;
this.colors = ["red", "green"];
}
Super.prototype.sayName = function() {
alert(this.name);
}
function Sub(name, age) {
Super.call(this, name); // 第二次
this.age = age;
}
inheritPrototype(Sub, Super); // 第一次
Sub.prototype.sayAge = function() {
alert(this.age);
}
var instance = new Sub("lucy", 20);
instance.sayName();
寄生式组合继承是被认为引用类型最理想的继承方式