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

JavaScript中的Prototypes

2015-07-14 15:07 537 查看
Prototype是什么?

prototype属性是一个初始化的空对象,像其它对象一样,它也可以添加成员属性和方法。




The Secret Link
每个JavaScript对象都有一个隐藏的属性,当这个对象被定义或者实例化的时候,这个属性会被添加到该对象中,这个属性的名称叫“__proto__”,它道出了原型链是如何被访问的。然而,在你的应用中直接方法__proto__不是一个好主意,因为所有浏览器都不认识它。

不要把__proto__属性和对象的prototype弄混了,它们是两个不同的属性。也就是说,它们是手拉着手齐头并进的。把它们区分开是很重要的,因为它们确实有点不容易理解。这是什么意思呢?让我来解释一下。当我们创建myObject函数时,我们实际上是定义了一个Function类型的对象。




Function是JavaScript中预定义的一个对象,它有自己的属性(比如:length和arguments)和方法(比如:call和apply),它也有自己的prototype对象和__proto__属性。也就是说,在JavaScript引擎的中有大量的代码类似下面这样:

实际上,可能不是像上面这么简单,这里仅仅是阐述原型链是如何工作的。
我们定义myObject作为一个函数并且给它一个参数name,从来没有给它设置任何诸如length这样的属性已经call这样的方法。既然是这样,那么为什么下面的语句还能正常输出呢?
这是因为,当我们定义myObject时,它创建了一个__proto__属性并且把这它的值设为Function.prototype。所以,当我们访问myObject.length时,它就在myObject中查找名为length的属性,它发现没找到,于是顺着这条链,通过__proto__链,找到这样一个属性,然后返回它。

你可能想要知道为什么length被设置为1而不是0或者其它数呢?其实是因为,myObject是Function的一个实例。



当一个对象的实例被创建时,__proto__属性被更新为指向构造器的prototype属性,在这个例子中,构造器的原型是Function。




另外,当你创建一个新的Function对象时,本地的Function构造器将记下参数个数并且相应的更新this.length,在本例中,是1。

如果,我们用new关键字创建一个myObject的实例,那么,__proto__将指向myObject.prototype,因为此时myObject是我们新创建的实例的构造器。



除此之外,还可以访问Function.prototype的本地方法,比如call和apply。现在我们访问myObject的getName方法:




Why is Using Prototype Better?
有一个例子,我们准备开发一个游戏并且一次需要大量的在屏幕上的对象,每个对象有自己的属性,比如横坐标、纵坐标、宽度、高度等等。

我们可能这样写:

这样写将会在内存中创建所有这些定义的对象,这不是一个好主意,因为这个将占用大量的浏览器内存,并且运行会非常慢,甚至停止响应。
当然,只有100个对象的话,可能不会发生这样的情况,但是仍然会对性能有影响,因为它需要查找100个不同的对象,而不仅仅是单个prototype对象。

How to User Prototype
为了让这个应用运行更快,我们可以重新定义GameObject的prototype属性,每个GameObject的实例将引用定义在GameObject.prototype中的方法,即使这些实例有它们自己的方法。

我们实例化GameObject对象100次

现在我们有一个包含100个GameObject实例的数组,所有实例有相同的prototyp,并且都有draw方法,这样一来,就能大幅减少应用所占用的内存资源。

当调用draw方法的时候,将关联相同的函数


Prototype is a Live Object
可以这么说,一个对象的prototype是一个灵活的对象。可以简单的这样理解,在我们创建完所有我们需要的GameObject实例以后,我们能够决定是画矩形还是画圆,只要相应地改变GameObject.prototype.draw方法即可达到这个目的。

现在,所有实例将画圆。

Updating Native Objects Prototypes
看下面的例子:

现在,我们能够对任意字符串使用trim方法,就像这样:
“ foo bar   “.trim();
// “foo bar”

对于这个例子,你可以在你的应用中使用它,但是随着时间的推移,浏览器可能实现了它,并且在

JavaScript的新版本中String对象的原型中包含了一个内置的trim方法。这就意味着你定义的trim方法会覆盖JavaScript中String对象内置的trim方法。为了避免这种情况,我们在定义这样一个函数之前可以先检查一下。

现在,如果JavaScript内置了trim方法,浏览器将使用内置的trim方法。

一般来讲,最好的方式是避免扩展内置对象,但是,如果有必要的话,规则也是可以打破的。

原文:http://code.tutsplus.com/tutorials/prototypes-in-javascript-what-you-need-to-know--net-24949

下面我总结一下:
Function对象是JavaScript的内置对象,它有自己的属性、方法、prototype以及__prototype__

所有对象都是Function的实例

JavaScript中的Function相当于Java中的Object类,JavaScript中的对象相当于Java中的类,JavaScript中的实例相当于Java中的对象(或者叫实例)。(反正我是这么理解的)

当我们定义一个对象或者创建一个对象的实例的时候,一个名字叫“__proto__”的属性会被添加到对象中。通过__proto__可以访问对象的原型链。__proto__对浏览器来说是不可用的,所以不能直接方法它。

对象的prototype是一个初始化的空对象,可以想其它对象一样给它添加属性和方法。

prototype属性使我们有能力给对象添加属性和方法。

对象的__proto__属性与prototype属性是两个不同的属性,但又密不可分。千万别把它们弄混了。

定义一个对象时,它的__proto__属性的值是构造器的prototype属性,即__proto__指向了构造器的prototype。当我们通过new关键字创建对象的实例时,这个新生成的实例的__proto__指向了这个对象的prototype,因为对于新的实例来说,它的构造器是构造它的这个对象,即new后面的那个。

关于__proto__和prototype,我是这样理解的:通过prototype,我们可以向当前对象添加方法和属性,通过__proto__,我们可以访问这个对象的原型链,也就是说,它提供了一种方式让我们可以访问父对象(即构造它的对象)。总之呢就是,prototype指向当前对象,__proto__指向父对象。

每个对象的实例都要关联对象的prototype中的方法

感觉prototype有点像Java中的Class。(纯属个人愚见)



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript prototyp