转:http://www.cnblogs.com/gppblog/archive/2010/01/20/1652091.html
1、原型(prototype)是什么?与构造函数和对象有什么关系?
Js中对象的prototype属性,是该对象的构造函数 的原型的引用。
图示说明:
——理解原型、构造函数(类)、对象的关系
《Javascript王者归来》一书中打了个很贴切的比方,习语有“照猫画虎”,可以理解为“照着‘某只猫’画出一类虎”,那么由这类虎构造 的具体的‘某只虎’也就继承了这只猫的所有属性。这里的“某只猫”就是原型,而“虎”就是类型(构造函数)。那么具体的“某只虎”就是构造函数“虎”的一 个对象实例。
用Js代码表示就是:“虎.prototype=某只猫”或“虎.prototype=new 猫()”、“某只虎=new 虎()”、“某只虎.prototype=某只猫”。
概念化:
- 所有的 构造函数都有一个prototype属性。当函数被定义的时候,prototype属性自动创建和初始化,初始化值是一个对象。这个原型对象只带有一个属 性constructor,它指回到和原型相关联的那个构造函数(这也就是每个对象都有一个constructor属性的原因)。
- 添 加给这个原型的任何一个属性,都会成为对应构造函数创建的对象的属性。即对象从它的原型那 里继承属性 。
2、prototype的特性
- 原型模式(prototype pattern)要求 一个类型(这里指构造函数)一个时刻只能有一个原型。
- 这个类型(构造函数)的所有实例(对象),必须满足原型关系的类型链。
—— 一个例子:
<
script
type
="text/javascript"
language
="javascript">
function
ClassA() { } //默认时ClassA.prototype=new Object();
var
ObjectA = new
ClassA();
function
ClassB() { this
.b = "hello"
; }
ClassB.prototype = ObjectA; //ClassB以ClassA的对象为原型
var
ObjectB = new
ClassB();
function
ClassC() { this
.c = "c"
; }
ClassC.prototype = ObjectB; //ClassC以ClassB的对象为原型
var
ObjectC = new
ClassC();
alert(ObjectC instanceof
ClassC);//true
alert(ObjectC instanceof
ClassB);//true
alert(ObjectC instanceof
ClassA);//true
alert(ObjectC instanceof
Object);//true
</
script
>
上面例子中的关系可用下图表示(略去内部的constructor和prototype属性的表示):
3、prototype的使用
(1)给类的原型对象添加或删除属性。
—— 这一操作将直接影响相应的类(构造函数)创建的所有对象。
例:
<
script
language
="javascript"
type
="text/javascript">
function
print(msg) {
document.write(msg + "<br/>"
);
}
function
Point(x, y) {
this
.x = x;
this
.y = y;
}
var
p1 = new
Point(1, 2);
var
p2 = new
Point(3, 4);
Point.prototype.z = 0; //给Point函数的原型添加z属性,赋初值0
print(p1.z);//输出0
print(p2.z);//输出0
</
script
>
(2)使用prototype创建大量副本
—— 一般情况下,用prototype创建复杂对象的大量副本比其他方式来copy对象要快得多。
- 以一个对象为原型,创建大量新的对象,正是原型模式(prototype pattern)的本质。
<
script
language
="javascript"
type
="text/javascript">
……
var
p1 = new
Point(1, 2);
var
points = []; //定义一个数组
function
PointPrototype() { } //定义一个空函数PointPrototype
PointPrototype.prototype = p1; //将PointPrototype的原型设置为对象p1
for
(var
i = 0; i < 10000; i++) {
points[i] = new
PointPrototype();
//因为PointPrototype的构造函数是空函数,所有它比直接构造p1的副本快得多。
}
</
script
>
(3)用prototype定义静态方法
—— 习惯上,将采用prototype定义的属性和方法称为“静态属性”和“静态方法”(或称为“原型属性”和“原型方法”)。将this定义的属性和方法称 为“公有属性”和“公有方法”。
<
script
language
="javascript"
type
="text/javascript">
function
Point(x, y) {
this
.x = x;
this
.y = y;
}
Point.prototype.distance = function
() {
return
Math.sqrt(this
.x * this
.x + this
.y * this
.y);
}//用prototype避免每次调用构造函数时对this.distance的赋值操作。
</
script
>
注意:尽量采用prototype定义对象方法,除非该方法需要创建闭包。