您的位置:首页 > Web前端 > JavaScript

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

2017-01-12 15:39 393 查看

继承模式

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

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() 方法接收两个参数:

用作新对象原型的对象(必选) ,仅一个参数时与Object( )方法类似;

为新对象定义额外属性的对象(可选),第二参数与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();

寄生组合式继承是引用类型最理想的继承范式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息