剖析JavaScript中的原型(Prototype)

简介: 转载请注明出处:http://blog.csdn.net/horkychen 上篇提到构造函数包含一个prototype是实现继承的关键,就是原型链的概念。

转载请注明出处:http://blog.csdn.net/horkychen

上篇提到构造函数包含一个prototype是实现继承的关键,就是原型链的概念。在JavaScript中当使用构造函数创建一个对象时,如下面的图示(来自<<JavaScript高级程序设计>>):

JavaScript为建构函数生成一个原型(Prototype)指向原型对象,包含了所有实例共享的对象。而原型中也有一个constructor指向建构函数,以起到标识的作用,说明我是谁”.建构函数本身也是一个普通函数,只是首字母大写了。

 

当通过访问实例的属性和方法时:

   a.如果实例定义了同名的属性或方法,使用之。

   b.否则,尝试调用原型的同名属性或方法。

 

这里有一个关键的准则:

     所有在建构函数中定义的属性和方法,各个实例各自拥有一份。

     所有在原型中定义的引用类型属性(基本类型除外)和方法,各个实例将共享使用。

 

下面是一个包含建构和原型两种方式的对象创建示例:

function Person(name)

{

                this.name = name;

}

Person.prototype =

{

                friends:["A","B"],

                introduceSelf : function()

                 {

                                 document.write("<p /> My name is "+this.name);

                                 document.write("<p /> My friends are "+this.friends);

                }

};

 

var horky = new Person("Horky");

horky.friends.push("C");

 

var arthas = new Person("Arthas");

 

horky.introduceSelf(); //My friends are A,B,C

arthas.introduceSelf(); //My friends are A,B,C

 

输出的结果是:

My name is Horky

My friends are A,B,C

 

My name is Arthas

My friends are A,B,C

认识这个特性很重要。一般我们希望类的方法可以重用,而不是各个实例再拥有一份实现,就可以放到原型的定义里面去。而对于子类需要自己定义的属性就可以放到建构函数中去。

 

既然原型也是一个对象,就可以按需要修改,比如扩展一下类的功能,随时加一个定义就可以了。

在上面代码后加入类似下面的代码:

……

horky.introduceSelf(); //My friends are A,B,C

arthas.introduceSelf(); //My friends are A,B,C

 

Person.prototype.saySomething = function(text)

{

                document.write("<p /> "+this.name+" says:"+text);

}

horky.saySomething("Hello, everyone!");

输出结果就会多一行:

Horky says:Hello, everyone!

理解了原型,我们再看一下继承。继承的要素是继承父类的属性和方法定义,而且属性可以自行更改。本身实例和原型之间就是继承关系的影子,因为访问是从下至上的。所以继承无非是要将子类的prototype变成一个指向父类原型的对象就可以了,如下图:

这就是<<JavaScript高级程序设计>>中所讲的较常用的寄生组合式继承。寄生指的是调用建构函数,组合则指的原型的运用。下面是示例代码:

function inheritPrototype(subType,superType){

var prototype=object(superType.prototype);  //创建对象

prototype.constructor=subType;                       //增强对象

subType.prototype=prototype;                          //指定对象

}

 

function SuperType(name){

this.name=name;

this.color=["red","blue","greed"];

}

 

SuperType.prototype.sayName=function(){

alert(this.name);

}

 

function SubType(name,age){

SuperType.call(this,name); //呼叫父类的建构函数

this.age=age;

}

 

inheritPrototype(SubType,SuperType); //将子类设定为继承自父类

 

SubType.prototype.sayAge=function(){ //增加一个子类方法

alert(this.age);

};

只要掌握前面所提原型的概念,JavaScript中使用很多OO的实现就很好理解了。比如所谓的模块(单件)模式之类的。

 

*<<JavaScript高级程序设计>>3版在这段代码下(P173)附的图6-6是属于前段代码的解释,放在这段代码下实在容易让人误解。

 

 

目录
相关文章
|
JavaScript 前端开发 Java
深入JS面向对象(原型-继承)(一)
深入JS面向对象(原型-继承)
30 0
|
28天前
|
JavaScript 前端开发
js开发:请解释原型继承和类继承的区别。
JavaScript中的原型继承和类继承用于共享对象属性和方法。原型继承利用原型链查找属性,节省内存但不支持私有成员。类继承通过ES6的class和extends实现,支持私有成员但占用更多内存。两者各有优势,适用于不同场景。
18 0
|
3月前
|
存储 JavaScript 前端开发
构造函数和原型的结合应用:轻松搞定JS的面向对象编程(三)
构造函数和原型的结合应用:轻松搞定JS的面向对象编程
|
3月前
|
设计模式 JavaScript 前端开发
构造函数和原型的结合应用:轻松搞定JS的面向对象编程(一)
构造函数和原型的结合应用:轻松搞定JS的面向对象编程
|
3月前
|
前端开发 JavaScript
JavaScript中的原型和原型链
JavaScript中的原型和原型链
|
3月前
|
JavaScript 前端开发
【面试题】最详尽的 JS 原型与原型链终极详解(一)
【面试题】最详尽的 JS 原型与原型链终极详解(一)
|
3月前
|
JavaScript 前端开发
手把手教你学会js的原型与原型链,猴子都能看懂的教程
手把手教你学会js的原型与原型链,猴子都能看懂的教程
|
3月前
|
存储 JavaScript 前端开发
构造函数和原型的结合应用:轻松搞定JS的面向对象编程(二)
构造函数和原型的结合应用:轻松搞定JS的面向对象编程
|
3月前
|
JavaScript 前端开发
JavaScript原型,原型链
JavaScript原型,原型链
|
1月前
|
JavaScript
JS数组增删方法的原理,使用原型定义
JS数组增删方法的原理,使用原型定义