最近一直在看书。上班看。下班看。
关于原型一直不懂。
有的地方说是简单的复制。有的地方说是引用。
现在结合本人自己的理解以及测试的代码,给大家解释一下。
(如有说错。请大侠指出。看官别拍砖哈~~)
?
代码如下:
<script> function a(){ } a.prototype.sayHi = function(temp){ alert(temp+" say HI") } function b(){ } b.prototype = a.prototype;//为了证明prototype的赋值(b继承a)是复制(大家理解为复制,会好理解点。) var A = new a; A.sayHi("a");//调用sayHi方法。结果是a say HI var B = new b; B.sayHi("b")//调用sayHi方法。结果是b say HI(说明调用的方法一致) A.sayHi = function(){ alert("Hello world!") }//大家应该都了解prototype的机制。会在原型链向上顺藤摸瓜到第一个方法。这里,我的目的就是改变当前对象的sayHi方法的引用(就是指向一个新的同名方法)。但是,原型链中的sayHi方法没变化。如果变化了,那么下面B.sayHi()肯定会跟随变化的。但事实却没有变化。 A.sayHi("a");//调用sayHi方法。结果是"Hello world B.sayHi("b")//调用sayHi方法。结果是b say HI(说明调用的方法一致,证明了prototype的赋值(b继承a)的确是一个个的复制字面量) a.prototype.goodbye = function(temp){ alert(temp+" GoodBye"); }//这里,我在a类的原型链中晚绑定一个新方法。(记住JS的晚绑定机制!) A.goodbye("a");//调用goodbye方法。结果是a GoodBye B.goodbye("b");//调用goodbye方法。结果是b GoodBye(JS的晚绑定特性!!) </script>
?
代码中的注释,我都是说的复制。
其实。JS中的对象包括Object和Function都是引用类型。
那为什么说是复制呢?
因为在第一次重写原型链中的sayHi方法的时候,是让A对象的sayHi方法重新引用到一个新的对象上。可是B对象的sayHi方法还是引用的内存中的原先的sayHi方法。这就是JS中鼎鼎大名的reference 。所以,代码中说的复制,其实更确切的说,应该是复制引用(我给这个机制起名为:references copy )!还是结合我的代码。其实2个sayHi方法都存在内存中,只是2个对象的指向不同而已。A的sayHi已经指向了新的改变了的方法,而B的还是指向原来的那个方法。这就想String类型的道理是一样的。
?
备注:
代码中的继承。我写的是b.prototype = a.prototype;
【备注:(这里是我后来看FF的监控,才知道的,上下两段代码是有区别的。感谢一位博友的指正。)】
请区别于b.prototype = new b;(js区别于java的特性还有:实例化类对象时,如果不传递参数,则可以省略括号。)
?
好了。就先解释这么多,本人的理解也有限。不到之处,请多多指正。
?
?
?
请先理解下
b.prototype = a.prototype; 和
b.prototype = new a();的区别。
如果b.prototype = a.prototype,那么a的静态方法a.sayHi(区别于原型上的方法)是不会影响到b的,
对b.sayHi的调用过程是b.sayHi --> b.prototype.sayHi(即 a.prototype.sayHi)--> ....
如果是b.prototype = new a();的话,
那么a.sayHi方法就在b的原型链上,
对b.sayHi的调用过程是b.sayHi--> b.prototype.sayHi --> a.sayHi(实例化的对象a) --> a.prototype.sayHi
PS:最好将构造函数名大写,对象名小写。
请先理解下
b.prototype = a.prototype; 和
b.prototype = new a();的区别。
如果b.prototype = a.prototype,那么a的静态方法a.sayHi(区别于原型上的方法)是不会影响到b的,
对b.sayHi的调用过程是b.sayHi --> b.prototype.sayHi(即 a.prototype.sayHi)--> ....
如果是b.prototype = new a();的话,
那么a.sayHi方法就在b的原型链上,
对b.sayHi的调用过程是b.sayHi--> b.prototype.sayHi --> a.sayHi(实例化的对象a) --> a.prototype.sayHi
PS:最好将构造函数名大写,对象名小写。
楼上的。
请问你自己测试过代码吗?
我标记为红色的部分。
一个类的静态方法可以被这个类的实例调用吗?
连这个类自己的实例都不能访问的静态方法。
继承了这个类的类的实例又怎么能访问??
建议你仔细思考下。
22.
23. a.prototype.goodbye = function(temp){
24. alert(temp+" GoodBye");
25. }//这里,我在a类的原型链中晚绑定一个新方法。(记住JS的晚绑定机制!)
26. A.goodbye("a");//调用goodbye方法。结果是a GoodBye
27. B.goodbye("b");//调用goodbye方法。结果是b GoodBye(JS的晚绑定特性!!)
||如前面所述,由于B调用的是a的原型链,所以对a原型链的修改会影响到B,这是JS的惰性绑定没有问题
28. </script>
请问你自己测试过代码吗?
我标记为红色的部分。
一个类的静态方法可以被这个类的实例调用吗?
连这个类自己的实例都不能访问的静态方法。
继承了这个类的类的实例又怎么能访问??
建议你仔细思考下。
这个我描述有误,不是静态方法,被大小写搞晕了。我重新讲下。
你这里举例有问题,你描述的问题是对的,结论是错误,我引用你的代码,加上我自己的注释:
1. <script>
2. function a(){
3.
4. }
5. a.prototype.sayHi = function(temp){
6. alert(temp+" say HI")
7. }
8. function b(){
9.
10. }
11. b.prototype = a.prototype;//为了证明prototype的赋值(b继承a)是复制(大家理解为复制,会好理解点。) ||这里b的原型直接指向了a的原型,而不是指向a的具体对象
12. var A = new a;
13. A.sayHi("a");//调用sayHi方法。结果是a say HI
14. var B = new b;
15. B.sayHi("b")//调用sayHi方法。结果是b say HI(说明调用的方法一致)
16. ||上面两个方法A.sayHi("a");和 B.sayHi("b")其实均调用了a.prototype上的方法
17. A.sayHi = function(){
18. alert("Hello world!")
19. }// 大家应该都了解prototype的机制。会在原型链向上顺藤摸瓜到第一个方法。这里,我的目的就是改变当前对象的sayHi方法的引用(就是指向一个新的同名方法)。但是,原型链中的sayHi方法没变化。如果变化了,那么下面B.sayHi()肯定会跟随变化的。但事实却没有变化。 ||这里重写了A的实例方法sayHi
20. A.sayHi("a");//调用sayHi方法。结果是"Hello world
21. B.sayHi("b")//调用sayHi方法。结果是b say HI(说明调用的方法一致,证明了prototype的赋值(b继承a)的确是一个个的复制字面量)
===============================================
这里b.prototype=A;而不是new a();
这条赋值语句放在A实例化后,对A的修改会影响到B
================================================
楼主调试一下下面代码:
function a(){
}
a.prototype.sayHi = function(temp){
alert(temp+" say HI")
}
function b(){
}
b.prototype =A; //对比 b.prototype = a.prototype!!
A = new a();
B = new b();
A.sayHi = function(){
alert("Hello world!")
}
B.sayHi();
有问题的话:
=====================================
===============================================
这里b.prototype=A;而不是new a();
这条赋值语句放在A实例化后,对A的修改会影响到B
================================================
楼主调试一下下面代码:
function a(){
}
a.prototype.sayHi = function(temp){
alert(temp+" say HI")
}
function b(){
}
b.prototype =A; //对比 b.prototype = a.prototype!!
A = new a();
B = new b();
A.sayHi = function(){
alert("Hello world!")
}
B.sayHi();
=====================================
我很高兴你这么专业。
不过,希望楼上的兄弟放出代码前,自己先测试下。
我清楚你想表达的。代码如下:
<script>
function a(){
}
a.prototype.sayHi = function(temp){
alert(temp+" say HI")
}
A = new a();
function b(){
}
b.prototype =A;
B = new b();
A.sayHi = function(){
alert("Hello world!")
}
B.sayHi();
</script>
首先。我要说明一下。
你的代码运行达到了你的预期效果。
即,调用B.sayHi();改变了a.prototype中定义的sayHi方法了。
可是这不能说明是改变了原型中的sayHi。
B中调用这个方法只是搜索到A(a的实例)中的的静态方法,就停止搜索了。
仔细想想,是不是这样的?
为了证明这一点,我写了如下代码。(仅仅是在最后添加了一个c。绿色标记出)
function a(){
}
a.prototype.sayHi = function(temp){
alert(temp+" say HI")
}
A = new a();
function b(){
}
b.prototype =A;
B = new b();
A.sayHi = function(){
alert("Hello world!")
}
B.sayHi();
var c = new a;
c.sayHi("c")
结果显而易见。
证明了其实原型链中的sayHi方法被没有被重写。
简言之,还是返回到JS中的原型链机制。一个方法被调用的时候,只是顺藤摸瓜搜索第一个同名的方法。如你说的,先搜自己的静态成员,然后是自己的prototype。然后是父类的静态成员,然后是父类的prototype。如此顺藤摸瓜上去,知道Object的prototype为止!我在原文中给这个机制起了个名字叫references copy。
可是,实质是怎么样的呢?当一个类或实例重新设置同名的方法的时候,其实是把这个类或实例的这个属性指向新的引用了。原来的prototype中的同名的方法并没有被冲掉。
希望能对你有帮助。
===============================================
这里b.prototype=A;而不是new a();
这条赋值语句放在A实例化后,对A的修改会影响到B
================================================
楼主调试一下下面代码:
function a(){
}
a.prototype.sayHi = function(temp){
alert(temp+" say HI")
}
function b(){
}
b.prototype =A; //对比 b.prototype = a.prototype!!
A = new a();
B = new b();
A.sayHi = function(){
alert("Hello world!")
}
B.sayHi();
我很高兴你这么专业。
不过,希望你在提交代码前,先自己运行下代码。正确了再提交。
看我绿色处。
首先你把一个对象赋给了b类的原型。正确,可以这么做。(不过,请记得在实例化A以后!!)
然后
有问题的话:
=====================================
有问题的话:
=====================================
这里面的问题是:
b.prototype = a.prototype;使b的原型指向a的原型,你重写了a的实例方法并不会影响到a原型上的方法,这时候b通过原形链仍然指向a的原型,a的原型方法也仍然还是alert(temp+" say HI"),只不过是a的实例方法覆盖了其原型方法。
请问这和b的复制云云的有什么关系????b仍然指向a的原型,无论a的实例方法写成什么对原型都没有影响,因为b总是执行a.prototype.sayHi。
你的文章中有些地方需斟酌:
1.
其实还可以写成b.prototype = new b;
你认为这两个一样吗??
2.
只是顺藤摸瓜搜索第一个同名的方法。如你说的,先搜自己的静态成员,
然后是自己的prototype。然后是父类的静态成员,然后是父类的prototype。
静态方法、实例方法、原型方法你搞清楚了吗???原型链中会搜索静态方法吗?
3.
b.prototype =A; //对比 b.prototype = a.prototype!!
我写这两个的对比只是想告诉你,如果你使用b.prototype = a.prototype实现b继承a的话,你对a实例方法的修改将不会影响到b的任何方法,除非你改变a原型方法,这样会影响到b。而你使用b.prototype =A的话,对具体实例A的修改则会影响到b,仅此而已。
4.这里的大小写真的搞的我头晕,具体实例用大写,构造函数用小写,楼主需要专业一点。
5.这篇文章错误百出,“顶”的人可能就楼主一个吧??
6。结束,不来了,怎么撞到这里来的,晕死。
这里面的问题是:
b.prototype = a.prototype;使b的原型指向a的原型,你重写了a的实例方法并不会影响到a原型上的方法,这时候b通过原形链仍然指向a的原型,a的原型方法也仍然还是alert(temp+" say HI"),只不过是a的实例方法覆盖了其原型方法。
请问这和b的复制云云的有什么关系????b仍然指向a的原型,无论a的实例方法写成什么对原型都没有影响,因为b总是执行a.prototype.sayHi。
你的文章中有些地方需斟酌:
1.
其实还可以写成b.prototype = new b;
你认为这两个一样吗??
2.
只是顺藤摸瓜搜索第一个同名的方法。如你说的,先搜自己的静态成员,
然后是自己的prototype。然后是父类的静态成员,然后是父类的prototype。
静态方法、实例方法、原型方法你搞清楚了吗???原型链中会搜索静态方法吗?
3.
b.prototype =A; //对比 b.prototype = a.prototype!!
我写这两个的对比只是想告诉你,如果你使用b.prototype = a.prototype实现b继承a的话,你对a实例方法的修改将不会影响到b的任何方法,除非你改变a原型方法,这样会影响到b。而你使用b.prototype =A的话,对具体实例A的修改则会影响到b,仅此而已。
4.这里的大小写真的搞的我头晕,具体实例用大写,构造函数用小写,楼主需要专业一点。
5.这篇文章错误百出,“顶”的人可能就楼主一个吧??
6。结束,不来了,怎么撞到这里来的,晕死。
首先。请你审视下,你现在的论点和原先的不一样。
原先,你想表明父类的原型里的内容是可以被改变的。(看你的例子。)
现在,你却又说父类的原型里的内容不能被改变。
你真的看懂我的意思吗?请你仔细看看我的原文。
总结1: b.prototype=a.prototype;
b.prototype=A;//这2种继承的区别你研究过吗?我说的b的实例调用方法的时候会有一个搜索父类的静态同名方法的过程,特指的是子类的prototype是父类的一个实例的情况下。如果子类的prototype是父类的prototype,另当别论!(我举的这个例子,你真的看懂了吗?!!)
总结2: 你一直强调是子类的方法是覆盖!(请看你自己的评论!)
我给你写的最后一段代码,已经证明了,只是引用重新定向而已。事实说明一切。而你自己也知道你的解释站不住。还在一个劲的指责别人的理论。(我放出的代码全是运行过的!你的呢?!我不修改,根本无法运行!我不是指责你,只是想说,请你放出代码前自己先测试。)你一直问,复制是什么意思,我在博文里说了很清楚了,是引用复制!OK?!你还不理解,就指责错误。和你说了这么多,真浪费时间!!
- spring @Scope("prototype")注解更新有关问题,寻求帮助
- 关于下载Nokia Prototype SDK4.0的有关问题
- prototype.js有没有解决浏览器兼容的有关问题 和 便于搜索引擎索引的有关问题
- 使人头晕向转的 prototype!解决思路
- Array.prototype.slice.call开个贴子!看看这玩意是什么东西!网上看到的不太明白。解决思路
- 用CSS添<ul> + prototype.js + cookiejar.js 作一个菜单
- prototype 的 $super是什么,该怎么解决
- ext this.model.prototype 有关问题
- AJAX(prototype)兑现的局部刷新搜索框实例
- prototype ajax驱除本地缓存
- prototype ajax传递参数乱码解决办法
- ajax prototype 批改 textbox 的值
- jquery prototype 主要区别?该怎么解决
- 为啥typeof Function.prototype==='function'
- 前端性能优化:施用Array.prototype.join代替字符串连接
- 前端性能优化:应用Array.prototype.join代替字符串连接
- instanceof 跟 prototype 关系
- 解决jquery 和 prototype 的冲突有关问题
- jQuery 跟 prototype 选择器的使用与注意事项
- 采取struts1.2+prototype,中文信息为双数时,显示正常,单数时,变成花符
- String.prototype.replace(str,func) 例中func的参数有关问题
- prototype 1.6.0.1上 getElementsByClassName 的bug
- prototype 遇到个有关问题 大家看看有没有遇到过
- prototype.js1.7.1在IE停getOffsetParent()会返回body
- js构造函数原型(prototype)有关问题分析(一段烂代码引发的博客)
- prototype.js 跟 jQuery.js ajax 调用
- javascript 类属性、类方法、种实例、实例属性、实例方法、prototype、proto_ 测试与小结
- ――prototype 有关问题
- javascript 类属性、类方法、种实例、实例属性、实例方法、prototype
- Struts 1.1 Validator 与 prototype 冲突 有关问题 解决(从51cto移过来)