javascript with 和 prototype属性

with语句

http://hi.baidu.com/wookoo/blog/item/5a7f260872c9fb32e8248821.html


  with 语句

使用该语句的意思是:在该语句体内,任何对变量的引用被认为是这个对象的属
性,以节省一些代码。

with object{

...}

所有在with语句后的花括号中的语句,都是在后面object对象的作用域的。

作用是:为语句设定默认对象。

|*with* (/object/)
   /statements/ |


        参数

object

新的默认对象。

statements

一个或多个语句,/object/ 是该语句的默认对象。


        说明

*with* 语句通常用来缩短特定情形下必须写的代码量。在下面的例子中,请注意
*Math* 的重复使用:

|x = Math.cos(3 * Math.PI) + Math.sin(Math.LN10)
y = Math.tan(14 * Math.E)|

当使用 *with* 语句时,代码变得更短且更易读:

|*with* (Math){
       x = cos(3 * PI) + sin (LN10)     
       y = tan(14 * E)
}|

 

|prototype的含义|

|http://zhidao.baidu.com/question/37280373.html?si=1|

|最佳答案

我们知道JScript中对象的prototype属性,是用来返回对象类型原型的引用的。我
们使用prototype属性提供对象的类的一组基本功能。并且对象的新实例会"继承"
赋予该对象原型的操作。但是这个prototype到底是怎么实现和被管理的呢?

对于对象的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>

JavaScript中什么是prototype原型对象?它有和作用?

http://zhidao.baidu.com/question/37219013.html?si=2

在JavaScript中,prototype对象是实现面向对象的一个重要机制。每个函数就是
一个对象(Function),函数对象都有一个子对象prototype对象,类是以函数的
形式来定义的。prototype表示该函数的原型,也表示一个类的成员的集合。在通
过new创建一个类的实例对象的时候,prototype对象的成员都成为实例化对象的成
员。
1、该对象被类所引用,只有函数对象才可引用;
2、在new实例化后,其成员被实例化,实例对象方可调用。
同时,函数是一个对象,函数对象若直接声明成员,不用被实例化即可调用。

|

|详解javascript类继承机制的原理 <http://jimichan.javaeye.com/blog/119815> |

|


    详解javascript类继承机制的原理 <http://jimichan.javaeye.com/blog/119815>

*关键字:* JavaScript 了解javascript   
本文着重解析javascript类继承机制,让你从底层了解javascript是怎样实现“继
承”这一概念的。
    jimichan在javaeye博客发布,转载请说明。
  目前 javascript的实现继承方式并不是通过“extend”关键字来实现的,而是通
过constructor function和prototype属性来实现继承。首先我们创建一个animal类
js 代码

 1. varanimal = function(){  //这就是constructor function 了
 2.    this.name = 'pipi';   
 3.    this.age = 10;     
 4.    this.height = 0;     
 5. }     
 6. //建立一个动物的实例   
 7. vara1 =  newanimal ();  


构造函数与其他普通函数区别在于,1.构造函数里有 this关键字,2.调用构造函
数是使用的new关键字。通过new运算符调用构造函数animal 后,系统就会返回一
个对象,这个对象就相当于
js 代码

 1. vara1 = { name:'pipi' ,age:10,height:0 } 
 2.  
 3. //或者 
 4. vara1 = newObject(); 
 5. a1.name='pipi'; 
 6. a1.age = 10; 
 7. a1.height = 0;

等同这样的方式来产生js对象。

到这里我们知道如何在js中定义一个类了,接下来我们展示如何写一个cat

js 代码

 1. varcat = function(){   
 2. this.play = function(){    
 3. alert('cat play')   
 4. }   
 5. }   
 6. cat .prototype = newanimal ();   
 7. //prototype 属性指向一个对象
 8. var c1 = new cat();


到这里,cat就继承了animal 对象,类cat的一个实例对象c1拥有属性
name,age,height,和方法play了。
那么prototype起到了一个什么样的作用呢?
prototype就好比一个指针,它指向一个object,这个object就称为子类对象的原
型。当cat的对象被创建的时候,由于cat的构造函数拥有prototype属性,那么cat
的实例就会间接指向这个原型对象了(说成间接的是因为每个object都有一个
constructor 属性指向它的构造函数)。
那么问题来了,“当我们修改对象 c1 的name属性的时候,会不会修改它prototype
的name属性值呢?”,答案是否定的。
接下来详细解析:
1.访问name属性: 首先当我们第一次访问c1.name的属性的时候,我们会得到值
“pipi”,这个和我们预料中的一样。但是计算过程你未必知道。
它计算的过程是这样的:第一步:检查c1对象中是否有name属性,找到的话就返回
值,没有就跳到第二步,显然没有找到,因为cat的构造函数中没有定义。第二
步:当第一步没有找时,去间接访问prototype对象所指向的object,如果在
prototype对象中找到的name属性的话,就返回找到的属性值。如果还是没有找到
的话,再去递归地寻找prototype对象的prototype对象(去找它的爷爷),一直到
找到name属性或者没有prototype对象为止。如果到最后还是没有找到name属性的
话就返回undefined。

2.设定name属性:当我们设定c1对象的name属性时,及调用 c1.name= ' new
name'; 这个过程就简单多了。首先检查是否对象已有该属性,若已存在则修改当
前值,若不存在则为该对象新增一个属性并设定当前值。值得一提的是,在设定值
的过程中没有去访问prototype属性。

为了加深理解,我们再看一个 read-write-read 的过程,第一次read的时候,由
于自己的对象没有name属性,那么就会返回的原型对象的name属性的值。第二步,
写入name的值,同样没发现本身对象有name属性,那么就在本身对象上新建一个
name属性,然后赋值。第三步,再次读取name属性,由于在第二步中已经新建了
name属性,此时就返回在第二步中设定的值。值得一提的是,在这三步中没有改变
原型对象的值。

好了,到此详细分析了 javascript对象是如果实现继承的,其实和其他的面向对
象语言不一样的是,javascript的继承机制是对象的原型继承而不是类型继承。

呵呵,欢迎看完,有不对的地方欢迎大家讨论!

posted @ 2011-12-16 08:22  ;姚元培  阅读(112)  评论(0编辑  收藏  举报