原文
http://www.xiaoxiaozi.com/2009/06/29/995/
最近折腾MSDP的东西,js的东西灰常之多,之前没有很好学,现在来还账 :=)
在之前的《javascript 构造函数和方法》一文中,我们知道,用构造函数把方法赋予其实例化的对象这样的效率实在让人不敢恭维。如果那样的话,构造函数创建的每一个每一个对象都会有相同的方法属性的副本。
在JavaScript中,有一种更为有效的声明方法、常量及其他能被类所有对象共享的属性的方式,那就是prototype原型
一个对象的原型,是由创建并初始化该对象的构造函数定义的。在JavaScript中,所有的函数都具有prototype属性,它引用了一个对象。虽然
原型对象在初始化时是空的,但是你在其中定义的任何属性都会被该构造函数创建的所有对象所继承。这也是JavaScript继承的实现原理。
在学习prototype(原型)的时候,我们首先要搞明白这样两个规则:
1. 使用原型可以大量减少每个对象对内存的需求量,因为对象可以继承许多属性。
2. 即使属性在对象被创建之后才被添加至原型中,对象也能够继承这些属性。
我们需要了解一下,原型里定义的属性,不是简单的被实例化的对象复制过去的,只是看起来好像是这些对象的属性了,这是很重要的概念。
看一个实例来理解一下:
//创建一个构造函数 “用户”
function User(name)
{
this.name = name;
}
//实例化一个用户——>老张
var 老张 = new User('老张');
//弹窗显示老张的名字
alert(老张.name);
//定义原型,注意这里对象“老张”已经被实例化了
User.prototype.favchannel = 'CCAV';
//弹窗显示老张最喜欢的电视台
alert(老张.favchannel);
虽然“老张”这个对象已经被实例化出来了,不过其仍然会继承原型定义的“最喜欢的频道”这个属性
注意,只有读属性的时候才会使用prototype,写属性的时候是不会用到prototype的。
首先我们来详细了解一下,什么时候会用到prototype。当读一个对象的属性时,其寻找这个属性的顺序是怎样的呢?例如:读取老张的favchannel属性:
第一步:去问老张,你有没有啥喜欢的频道啊? 老张如果有的话就是:嗯呐,我喜欢CCAV,如果没有就说我不知道啊,问我老大吧,他说我喜欢啥,俺就喜欢啥。
第二步:问老张的构造函数的原型,如果原型内定义了,就会告诉你,我的小弟都喜欢CCAV,除非有的非常有个性可能喜欢某岛国的小电影频道。如果原型内也没定义,就会告诉你,去找我们经理,经理知道。
第三步:去问经理,即Object的prototype,如果经理说他们一般都喜欢CCAV,那么就是CCAV,如果经理也不知道,那就返回undefined。
所以顺序是 老张——>User prototype——>Object prototype
那么为啥写属性的时候不用prototype呢?举个例子你就清楚了
//老李是一个新的用户
var 老李 = new User('老李');
//老李喜欢小电影
老李.favchannel = 'JAPANTV';
//弹窗显示JAPANTV
alert(老李.favchannel);
//弹窗显示老张还是中意CCAV
alert(老张.favchannel);
如果,写属性也去改prototype的时候,那改变其中任何一个对象的属性,比如老李现在得意JAPANTV,如果也去改原型的话,老张也只能得意JAPANTV了。。
上面我们已经了解了,属性的继承(从原型处继承)只发生在读属性时。另外,原型对象的属性被一个类的所有对象共享,所以通常只用它们来定义类中所有对象相同的属性。例如我们可以定义“圆”这个类的PI值为1.34。