js继承

1、原型链:

构造函数1的prototype指向原型1,实例1的prototype指向原型1;如果这个实例是一个构造函数2,就是构造函数2的原型2指向原型1,构造函数2的prototype指向原型2,实例2的prototype指向原型2。

子类型.prototype = new 父类型();

function SuperType(){
    this.property = true; //SuperType构造的所有实例中的property都是true
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
};
function SubType(){
    this.subproperty = false;
}
//继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
    return this.subproperty;
};
var instance = new SubType(); 
//SubType.prototype、instance、SuperType.prototype的constructor都是SuperType;SubType的constructor是Function
alert(instance.getSuperValue());//true

确定原型和实例的关系,可以用:

b.isPrototypeOf(b.prototype) //true  或者  b.prototype instanceof b  //true

原型链中用字面量添加新方法会导致原型链中断

原型链的继承缺点:原型属性包括引用类型的值;在创建子类型的实例时不能像超类型的构造函数中传递参数。

2、借用构造函数(又称:伪造对象 或者 经典继承):

通过使用apply()和call()方法,在新创建的对象上执行构造函数:

function SuperType(name){
    this.colors = ['red','yellow','green'];
    this.name = name;
}
function SubType(){
    //继承了SuperType
    SuperType.call(this,'jack');
}
var instance1 = new SubType();
instance1.colors.push('black'); 
alert(instance1.colors);  //red yellow green black
//每个实例都各自调用初始化代码
var instance2 = new SubType();
alert(instance2.colors);  //red yellow green
alert(instance2.name); //jack

但是这种用法会在每次声明变量的时候重复声明函数。

3、组合继承:(又用call或apply,又用prototype)

function SuperType(name){
    this.name = name;
    this.colors = ['red','blue','green'];
}
//方法放到原型中复用
SuperType.prototype.sayName = function(){
    alert(this.name);
};
function SubType(name,age){
    //除方法外,其他属性可以用call或apply每次定义
    SuperType.call(this,name);
    //先调用超类型的构造函数,再添加子类型中定义的属性
    this.age = age;
}
//这里还是继承了SuperType,主要是为了用SuperType中的方法
SubType.prototype = new SuperType();
//这句可有可无SubType.prototype.constructor = SubType;
//SubType原型中也有自己的方法
SubType.prototype.sayAge = function(){
    alert(this.age);
};
var instance1 = new SubType('Nicholas',29);
instance1.colors.push('black');
alert(instance1.colors);  //red,blue,green,black
instance1.sayName();  //Nicholas
instance1.sayAge();  //29

var instance2 = new SubType('Greg',27);
alert(instance2.colors);  //red,blue,green
instance2.sayName();  //Greg
instance2.sayAge();//27

这种继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,是js中最常用的继承模式,但是也有小缺陷:无论在什么情况下,都会调用两次超类型构造函数:一次是创建子类型原型的时候,一次是在子类型构造函数内部。

4、原型式继承:也存在对象引用的问题。

function object(o){
function F(){}
F.prototype = o;
return new F();
}
var person = {
name:'Honey',
friends:['shelly','Van']
};
var anotherPerson = object(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Amy');

var anotherPerson2 = object(person);
anotherPerson2.name = 'haha';
anotherPerson2.friends.push('eiya');
//对象的引用
alert(person.friends);//'shelly,Van,Amy,eiya'

5、寄生式继承:不能做到函数复用。

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

6、寄生组合式继承:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。是最理想的继承范式。

function SuperType(name){
    this.name = name;
    this.colors = ['red','blue','green'];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
}
//在这里先把SubType的属性都加上
function SubType(name,age){
    SuperType.call(this.name);
    this.age = age;
}
//把SubType的prototype加上方法属性
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function(){
    alert(this.age);
}
//这里只取了SuperType.prototype的属性值
function inheritPrototype(subType,superType){
    var prototype = Object.create(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
} 
 











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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值