对于对象的prototype属性的说明,JScript手册上如是说:所有 JScript 内部对象都有只读的 prototype 属性。可以向其原型中动态添加功能(属性和方法),但该对象不能被赋予不同的原型。然而,用户定义的对象可以被赋给新的原型。
下面我们看三个经典的prototype属性的使用示例。
1、为脚本环境内建对象添加方法:
程序代码
Array.prototype.max = function()
{
var i, max = this[0];
for (i = 1; i < this.length; i++)
{
if (max < this[i])
max = this[i];
}
return max;
};
2、为用户自定义类添加方法:
程序代码
function TestObject(name)
{
this.m_Name = name;
}
TestObject.prototype.ShowName = function()
{
alert(this.m_Name);
};
3、更新自定义类的prototype:
程序代码
function TestObjectA()
{
this.MethodA = function()
{
alert('TestObjectA.MethodA()');
}
}
function TestObjectB()
{
this.MethodB = function()
{
alert('TestObjectB.MethodB()');
}
}
TestObjectB.prototype = new TestObjectA();
第三个很眼熟吧?对啊,它就是我们前面介绍的原型继承法呀~~ 不过今天我们不是研究"继承",之所以可以这样来实现一种继承,只是利用了prototype属性的一个副作用而已。
prototype还有一个默认的属性:constructor,是用来表示创建对象的函数的(即我们OOP里说的构造函数)。constructor属性是所有具有prototype属性的对象的成员。它们包括除Global和Math对象以外的所有JScript内部对象。constructor属性保存了对构造特定对象实例的函数的引用。
弄清楚了JScript中prototype属性怎么使用后,下面我们再来深入的研究它。
上面的文章中我罗列了一下prototype属性在JScript中的各种用法,但是prototype这个东西却不是JScript创造出来的,JScript实际上是使用了我们设计模式中prototype pattern的一种衍生形式。下面我先简单的说一下prototype pattern,然后再来看到底JScript中的prototype是怎么回事?!
What's prototype pattern?
Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
继续了解到底什么是prototype pattern,可以参看'设计模式之Prototype(原型)'这篇文章,即使不懂Java也没有关系,把它的代码都当C#看就行了。
搞清楚什么是原型了吧?反正记着一点,prototype pattern是的实现是依赖于clone这个操作的,当然要shallow copy还是deep copy的clone看自己的需要了。
下面我们继续说JScript里的prototype,为什么我们说它和prototype pattern里的prototype不一样呢?! 这个不是我说就说出来的,也不是我吹出来的,看看这个示例,你就能大概糊涂:
程序代码
<script language="javascript">
function RP()
{
RP.PropertyA = 1;
RP.MethodA = function()
{
alert("RP.MethodA ");
};
this.PropertyA = 100;
this.MethodA = function()
{
alert("this.MethodA");
};
}
RP.prototype.PropertyA = 10;
RP.prototype.MethodA = function()
{
alert("RP.prototype.MethodA");
};
</script>
不要着急,还没有开始做示例,只是给出了我们用来演示的一个类。RP是什么?rpwt吗?当然不是了,RP是ResearchPrototype了。好了不废话了,看示例及结果分析。
程序代码
<script language="javascript">
rp = new RP();
alert(RP.PropertyA);
RP.MethodA();
alert(rp.PropertyA);
rp.MethodA();
</script>
运行结果闪亮登场:
1
RP.MethodA
100
this.MethodA
这个%$@#^$%&^...,不要着急,继续看哦!
程序代码
<script language="javascript">
rp = new RP();
delete RP.PropertyA;
alert(RP.PropertyA);
delete RP.MethodA;
RP.MethodA();
delete rp.PropertyA;
alert(rp.PropertyA);
delete rp.MethodA;
rp.MethodA();
</script>
运行结果再次登场:
程序代码
undefined
A Runtime Error has occurred.
Do you wish to Debug?
Line: 32
Error: Object doesn't support this property or method
10
RP.prototype.MethodA
好玩吧,看出来什么名堂了吗?这里的RP.PropertyA和RP.MethodA只是用来做参照的,可是怎么把this.PropertyA和this.MethodA都delete了,还能出来结果,而且还是prototype导入的属性和方法呢?
这就是JScript的prototype和prototype pattern中prototype最大的不同了,JScript中的这个所谓的prototype属性其实是个语言本身支持的特性,这里没有发生任何的copy,不管shallow还是deep的。对于JScript的解释引擎,它在处理"."或"[keyName]"引用的对象的属性和方法时,先在对象本身的实例(this)中查找,如果找到就返回或执行。如果没有查找到,就查找对象的prototype(this.constructor.prototype)里是否定义了被查找的对象和方法,如果找到就返回或执行,如果没有查找到,就返回undefined(对于属性)或runtime error(对于方法)。
正因为prototype导入类实例的属性或方法是动态查找的,所以我们才能对系统内部对象添加prototype属性和方法,比如给String对象添加trim方法:
程序代码
<script lanuage="javascript">
String.prototype.trim()
{
return this.replace(/(^\s+)|(\s+$)/g, "");
}
</scritp>
显然JScript中的这种用法也是prototype pattern中的prototype不能解释和支持的。
这下对于JScript OOP中原型继承法的理解因该没有任何的障碍了吧?同时也应该明白为什么原型继承法有那么大的天生缺陷了吧?当然如果有任何问题,欢迎继续讨论。
附演示示例源代码:
程序代码
<html>
<head>
<meta name="author" content="birdshome@博客园">
<title>JScript Prototype Research</title>
</head>
<body>
<script language="javascript">
function RP()
{
RP.PropertyA = 1;
RP.MethodA = function()
{
alert("RP.MethodA ");
};
this.PropertyA = 100;
this.MethodA = function()
{
alert("this.MethodA");
};
}
RP.prototype.PropertyA = 10;
RP.prototype.MethodA = function()
{
alert("RP.prototype.MethodA");
};
</script>
<script language="javascript">
rp = new RP();
delete RP.PropertyA;
alert(RP.PropertyA);
delete RP.MethodA;
RP.MethodA();
delete rp.PropertyA;
alert(rp.PropertyA);
delete rp.MethodA;
rp.MethodA();
</script>
</body>
</html>
分享到:
相关推荐
对于对象的prototype属性的说明,JavaScript手册上如是说:所有 JavaScript内部对象都有只读的 prototype 属性。可以向其原型中动态添加功能(属性和方法),但该对象不能被赋予不同的原型。然而,用户定义的对象可以...
prototype属性的使用说明: 1. prototype属性的简单使用: 可以通过为某个构造函数的prototype属性赋予一个新的函数,来实现给所有该构造函数的实例添加新的方法。例如,Number.prototype.add 方法可以在任意Number...
本压缩包文件“prototype文件以及使用说明.rar”显然提供了关于如何利用和理解`prototype`的相关资料,下面我们将深入探讨`prototype`的相关知识点。 1. **对象原型与原型链** 每个JavaScript对象都有一个内部属性...
尝试让对象去引用prototype属性时,结果是undefined,这说明对象不能直接引用prototype。这一点是理解和使用prototype属性时必须清晰的。 再来深入探讨prototype的含义。当定义一个函数时,JavaScript会自动为该...
JavaScript中的prototype属性是理解其原型继承模型的关键部分。它被翻译为“原型”,是JavaScript语言中一个非常特殊的属性,它在实现对象的继承机制中扮演了核心角色。 在JavaScript里,prototype属性属于函数对象...
2. "Prototype_1.4.doc" - 这个文件可能是Prototype 1.4版本的文档,以.doc格式呈现,可能包含详细的类库介绍、方法和属性说明,以及可能的使用案例。 **知识点详解** 1. **Prototype库基础**:Prototype库提供了...
一说到prototype很多人可能第一个想到的是著名的prototype.js框架,当然我们今天说的不是它,而是Javascript中的prototype属性,一般都被翻译为“原型”。这是一个比较特殊的属性,Javascript中的继承一般都依赖这...
如果找到了`Person.prototype`,则说明`person`是`Person`的实例。 需要注意的是,`instanceof`对于检测原型链中的继承关系也非常有用。当一个对象继承自另一个对象时,子对象的原型链中也会包含父对象的`prototype...
1. Object.extend:这是Prototype库的核心功能之一,允许用户向任何对象添加新的属性或方法,实现类继承的概念。 2.$$:这个快捷函数用于选择DOM元素,支持CSS选择器,类似于jQuery的$函数。 二、DOM操作 1.$$函数...
`prototypeAPI` 文件可能是 Prototype.js 1.6 的 API 文档,包含了详细的函数说明、参数和示例。通过查阅这份文档,开发者可以更全面地了解每个方法的用法,以便在实际项目中有效地应用。 综上所述,Prototype.js ...
`Object.extend`方法则提供了对象属性和方法的继承机制,使得一个对象能够继承另一个对象的特性。`bind`方法则是用来改变函数调用时的上下文(即`this`关键字指向的对象),这对于事件处理和回调函数特别有用。 总...
对于对象的prototype属性的说明,JScript手册上如是说:所有 JScript 内部对象都有只读的 prototype 属性。可以向其原型中动态添加功能(属性和方法),但该对象不能被赋予不同的原型。然而,用户定义的对象可以被赋给...
以上就是 JavaScript 中 prototype 的使用说明,它既是 JavaScript 实现继承、多态等面向对象编程特性的核心机制,也是一些JavaScript 高级特性如原型继承、原型链等的基础。理解 prototype 的工作方式对于深入学习 ...
在JavaScript中,每一个函数都有一个`prototype`属性,这个属性指向一个对象,该对象的属性和方法可以被函数实例共享。当尝试访问实例的一个属性时,如果在实例本身找不到,JavaScript会向上搜索到其构造函数的`...
- `options`:一个对象,包含以下属性: - `method`:请求方式,默认为`GET`。 - `parameters`:请求参数,可以是对象或字符串形式。 - `onSuccess`:请求成功时的回调函数。 - `onFailure`:请求失败时的回调...
例如,`Object.extend()`函数用于合并两个或更多对象的属性,使得代码更易于维护和复用。此外,`Function.prototype.bind()`方法允许我们固定函数的作用域,确保函数在调用时总是以特定的对象为上下文,这在处理事件...