《JS高程(3)》原型链继承模式 -第6章笔记(04)

继承模式

原型链实现继承时,将对象实例视作一个子类原型创建对象实例时,其本身从构造函数中继承的实例属性,此时成为了原型属性,原型属性中包含了”引用类型值”,导致子类原型的属性会被所有实例共享。

function SuperType(){
    this.color = ['red', 'blue' , 'yellow'];
}

function SubType(){}

SubType.prototype = new SuperType()

var instance1 = new SubType();
instance1.color.push ('white');
alert(instance1.color); // red,blue,yellow,white

var instance2 = new SubType();
alert(instance2.color); // red,blue,yellow,white

单独借用构造函数也并未解决这问题

1. 组合继承

模式:原型链+借用构造函数

  • 使用原型链实现对原型属性和方法的继承;
  • 借用构造函数来实现对实例属性的继承。
function SuperType(name){
    this.name = name;
    this.color = ['red', 'blue' , 'yellow'];
}

SuperType.prototype.sayName = function(){
    alert(this.name);
}

function SubType(name, age){
    //继承属性 超类
    //获得name和color属性
    SuperType.call(this, name);
    this.age= age;
} 

//继承方法
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
    alert(this.age)
}

var instance1 = new SubType("Nicholas", 29);
instance1.color.push("black");
console.log(instance1.color); //["red", "blue", "yellow", "black"]
instance1.sayName();
instance1.sayAge();

var instance2 = new SubType("Greg", 27);
console.log(instance2.color); //["red", "blue", "yellow"]
instance2.sayName();
instance2.sayAge();
  • SubType构造函数,通过call()方法调用SuperType构造函数是传入name参数,此时获得name与color属性;(借用构造函数)

  • 将SuperType的实例赋值给SubType的原型;(原型链)

  • instanceof 和 isPrototypeof()能够识别基于组合继承创建的对象。


2.原型式继承

借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。多用于让一个对象与另一对象保持类型的情况,不必在创建构造函数。


function object (o) {
    // 创建临时构造函数
    function F(){}

    // 将传入的对象作为构造函数的原型
    F.prototype = o;

    // 返回临时构造函数的实例
    return new F();
}

//基础对象
var person = {
    name : "Nicholas",
    friends : ["Shelby", "Count", "Van"]
};

// 返回新对象,以person为原型
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
console.log(anotherPerson.friends); //["Shelby", "Count", "Van", "Rob"]

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
console.log(yetAnotherPerson.friends); //["Shelby", "Count", "Van", "Rob", "Barbie"]
console.log(person.friends); //["Shelby", "Count", "Van", "Rob", "Barbie"]

基本类型值 :

  • Undefined、Null、Boolean、Number和String
  • 引用时是对实际原型进行了一次复制,通过引用值对基本类型值进行修改的结果,并不会被共享。每次引用就像对实际值进行了一次克隆,但克隆值得修改并不会影响被克隆原型。

引用类型值 :Object 、 Array 、 Date 和 RegExp

  • 对象实例中的引用类型属性是一个指向对象实际位置的指针,所有实例都指向同一个位置,当其中一个实例对指针地址中的属性进行修改后,会影响之后所创建的变量。
//判断对象类型
function isArray(o) { 
  return Object.prototype.toString.call(o) === '[object Array]';  
//Array可以换成其它类应用以验证 
}
var str = "string";
alert(isArray(str)); //false

ES5新增: Object.create( ) 原型式继承

  • Object.create() 方法接收两个参数:
    1. 用作新对象原型的对象(必选) ,仅一个参数时与Object( )方法类似;
    2. 为新对象定义额外属性的对象(可选),第二参数与Object.defineProperties(obj, props)方法第二参数格式相同:每个属性都是通过自己的描述符定义的。
var person = {
    name : "Nicholas",
    friends : ["Shelby", "Count", "Van"]
};
var anotherPerson = Object.create(person,{
    name:{
        value:"Grey"
    },
    age:{
        value:15
    }
});
console.log(anotherPerson.name ); // Grey
console.log(anotherPerson.age);  // 15

3.寄生式继承

创建一个用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回该对象。

// 寄生式构造函数
function createAnother(o){

    // Object()函数可换成其他返回新对象的函数
    var clone = Object(o);
    clone.sayName = function(){
            alert('name');
            };
    return o;
}
var o = {
        name:'Grey',
        age:16
        };  

// 返回的新对象,具有基础对象的方法和属性,并拥有自己的sayName方法
var person =createAnother(o);
person.sayName(); 

寄生式继承为对象添加的函数不能复用


4.寄生组合式继承

JavaScript最常用的继承模式
通过创建一个过渡对象,作为超类型和子类型的桥梁,减少超类的调用次数,

// 组合继承实例

function SuperType(name){
    this.name = name;
    this.color = {"red", "blue", "green"};
};

SuperType.prototype.sayName = function(){
    alert(this.name);
};

function SubType(name, age) = function(){
    // 第二次调用SuperType()
    SuperType.call(this, name);
    this.age = age;
}

// 第一次调用SuperType()
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    alert(this.age);
}

inheritPrototype()函数接受两个参数: 子类型构造函数和超类型构造函数。
创建步骤:① 创建超类型原型的副本;
② 为副本指定constructor属性方向;
③ 将副本赋值给子类型的原型。

    // 寄生组合式继承的最简单形式
function inheritPrototype(subType, superType){

    // 创建对象 作为超类原型的副本
    var prototype = object (superType.prototype);

    // 修改副本的constructor属性的指向
    prototype.constructor = superType;

    // 将prototype中存放的副本赋值给子类的原型
    subType.prototype = prototype;
}

    function SuperType(name){
        this.name = name;
        this.color = {"red", "blue", "green"};
    }

    SuperType.prototype.sayName = function(){
        alert(this.name);
    };

    function SubType(name, age){
        //调用了一次SuperType
        SuperType.call(this.name);
        this.age = age;
    };
    //替换前面为子类型原型赋值的语句
    inheritPrototype(SubType, SuperType);

    SubType.prototype.sayAge = function(){
        alert(this.age);
    };
  • 避免了在SubType.prototype上面创建不必要的、多余的属性;

  • 原型链保持不变,能够正常使用instanceof 和isPrototypeOf();

  • 寄生组合式继承是引用类型最理想的继承范式。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值