学习javascript遇到的一个问题。

wyman25 2011-11-19 12:43:08
我在学习js继承特性中,在尝试call与prototype比较的时候,遇到了这个问题:

<script type="text/javascript">
var father=function(){
this.name="father";
}
var child=function(){
child.prototype=new father();
}
var son=new child();
alert(child.prototype.name);
alert(son.name);
</script>

IE8和chrome第一个弹出框是"father",但第二个弹出框却是undefined。百思不得其解:既然第一个弹出框是"father",也就是说child.prototype的确是new father()这个对象,但为什么son并没有获得father.name属性呢?然后我将“child.prototype=new father();”这句放在child函数外面,变成:

<script type="text/javascript">
var father=function(){
this.name="father";
}
var child=function(){
//child.prototype=new father();//放到child外面执行
}
child.prototype=new father();
var son=new child();
alert(child.prototype.name);
alert(son.name);
</script>

结果两个弹出框都是"father"。为什么这语句在child里面执行,son就不能继承到father(即使son的构造函数child的prototype已经是new father())?为什么放在外面就可以? 是不是域的问题?求解答!!!
我在js版的积分不多,请不要嫌弃
...全文
285 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
峭沙 2011-11-23
  • 打赏
  • 举报
回复
其实变量的传递并不是js独有的特性,一般的编程语言都一样,基本类型是值传递,对象是引用传递
liangws 2011-11-22
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 zeewendotnet 的回复:]

就一点基础只是不是很牢固导致一个问题几乎解决不了,再次多谢liangws,不过能不能告诉我还有哪些更深入的特性要去弄懂的?我google了很久,最深入的都还是prototype的原理。
算了,结贴。
[/Quote]
js特性太多了。。你可以看看周爱民的 javascript语言精髓与编程实践,里面说了很多js特别的地方
wyman25 2011-11-22
  • 打赏
  • 举报
回复
就一点基础只是不是很牢固导致一个问题几乎解决不了,再次多谢liangws,不过能不能告诉我还有哪些更深入的特性要去弄懂的?我google了很久,最深入的都还是prototype的原理。
算了,结贴。
liangws 2011-11-22
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 zeewendotnet 的回复:]

昨天又想了一个晚上,又要多谢lingws,我想我想通了:
第一次new的时候还是像我之前说的那样创建了空对象,空对象的__proto__指向child.prototype,然后执行“child.prototype=new father();”。这时如lingws所说,prototype是引用传递,son.__proto__和child.prototype已经指向不同的对象了,前者是child原……
[/Quote]
楼主真是好学啊~其实自己想通的问题是最好的!
峭沙 2011-11-22
  • 打赏
  • 举报
回复
变量的传递
峭沙 2011-11-22
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 zeewendotnet 的回复:]

昨天又想了一个晚上,又要多谢lingws,我想我想通了:
第一次new的时候还是像我之前说的那样创建了空对象,空对象的__proto__指向child.prototype,然后执行“child.prototype=new father();”。这时如lingws所说,prototype是引用传递,son.__proto__和child.prototype已经指向不同的对象了,前者是child原……
[/Quote]呵呵,恭喜你答对了。这问题的关键就是new的实现方式以及变量的值传递问题
wyman25 2011-11-22
  • 打赏
  • 举报
回复
昨天又想了一个晚上,又要多谢lingws,我想我想通了:
第一次new的时候还是像我之前说的那样创建了空对象,空对象的__proto__指向child.prototype,然后执行“child.prototype=new father();”。这时如lingws所说,prototype是引用传递,son.__proto__和child.prototype已经指向不同的对象了,前者是child原来的prototype对象,后者才是new father()。所以第一次new时候,son是没有name属性的。我后来在"var son=new child();"后面加了一句做验证:alert(son.__proto__==child.prototype),输出是false(chrome和ff,IE8好像不允许访问__proto__,值是undefind,输出false)。
对于lingws六楼的例子:child.prototype.name = "123"; //改变副本,不改变引用,child.prototype执行的仍然是当初默认的chil.prototype,并且和son.__proto__的指向是相同的,只是加了个name属性。
wyman25 2011-11-20
  • 打赏
  • 举报
回复
嗯..我其实还没有停止想这个问题,我再思考一下你得话。顺便问一句:lingws是怎样学到js这些东西的?看什么书,或者是什么资料?我在google上搜很久,最深入的都是prototype的一些原理,更深入的东西已经找不到了,不知道是那些方面的资料?
liangws 2011-11-20
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 zeewendotnet 的回复:]

经过一天的思考google加分析liangws的说话,我想我已经想通了:
首先,当浏览器执行到“var son=new child();”的时候,遇到了new的时候,就开辟了内存创建了对象(可以认为是一个空对象,这也是为什么new后面的构造函数叫“构造函数”的原因),创建了这个空对象的时候同时又将child函数的prototype赋值给了这个空对象(实际上是:这个空对象的__proto__指针……
[/Quote]
其实差不多。但是关键点没理解到
然后执行完这些后,再执行接下来的构造函数里面的代码,也就是“child.prototype=new father();”但很可惜,son的__prototype__已经指向了默认的child.prototype了(而且child.prototype并不是father对象,所以没有name属性),这时再设置child.prototype为new father()已经错失了赋予那个空对象任何father的属性的时机了

其实他已经设置对了。但是prototype是对象,你只改变了对象的引用,影响到的只是后面new出来的实例
我6楼的例子,改变的是prototype的副本,所以直接就影响到当前的实例了,再放出例子,楼主参考下
其实关键点是对象是引用传递

var father=function(){
this.name="father";
}
var child=function(){
// child.prototype=new father();
child.prototype.name = "123"; //改变副本,不改变引用,
}
var son=new child();
alert(child.prototype.name);
alert(son.name);




wyman25 2011-11-20
  • 打赏
  • 举报
回复
经过一天的思考google加分析liangws的说话,我想我已经想通了:
首先,当浏览器执行到“var son=new child();”的时候,遇到了new的时候,就开辟了内存创建了对象(可以认为是一个空对象,这也是为什么new后面的构造函数叫“构造函数”的原因),创建了这个空对象的时候同时又将child函数的prototype赋值给了这个空对象(实际上是:这个空对象的__proto__指针指向了child.prototype,需要注意的是此时的child.prototype仍然是默认的prototype,因为还没有执行到构造函数里面那句“child.prototype=new father();”)。然后执行完这些后,再执行接下来的构造函数里面的代码,也就是“child.prototype=new father();”但很可惜,son的__prototype__已经指向了默认的child.prototype了(而且child.prototype并不是father对象,所以没有name属性),这时再设置child.prototype为new father()已经错失了赋予那个空对象任何father的属性的时机了(形象的来说就是:对象都已经建好了,再给构造函数设置prototype有个鸟用,留给下一个对象用吧!)。所以,liangws后来加的var son1=new child()就能有这个name属性就是这个原因。最后,构造函数执行完,也就是构造好原来那个空对象后,就接着将这个空对象赋值给变量son,整个对象创建的过程完成。所以我原来的代码其实等同于:

<script type="text/javascript">
var father=function(){
this.name="father";
}
var child=function(){
//child.prototype=new father();//放到外面,在son对象创建后执行
}

var son=new child();
child.prototype=new father();//在son已经创建后执行,再来设置son的构造函数的prototype已经对son没有任何意义了,son不会回过头来继承father任何成员。
alert(child.prototype.name);
alert(son.name);
</script>

liangws 2011-11-19
  • 打赏
  • 举报
回复
楼主试试?简单来说。引擎在new的时候会先将prototype的引用放到实例中,然后再执行构造函数里面的code..你第一次new的时候child.prototype=new father();还没执行,引擎就将prototype的引用放到实例中了。所以son没有name这个属性。。第二次new的时候,在第一次的child.prototype=new father();已经执行了,所以son1有name
var father=function(){
this.name="father";
}
var child=function (){
child.prototype=new father();
}
var son=new child();

alert(child.prototype.name);
alert(son.name);

var son1=new child();
alert(son1.name);

wyman25 2011-11-19
  • 打赏
  • 举报
回复
谢谢liangws,有空请再指教提点一下,谢谢。
liangws 2011-11-19
  • 打赏
  • 举报
回复
3楼明显是错的,楼主,我现在有点忙,空闲的时候再解释
代码改一下


var father=function(){
this.name="father";
}
var child=function(){
// child.prototype=new father();
child.prototype.name = "123"; //改变副本,不改变引用,
}
var son=new child();
alert(child.prototype.name);
alert(son.name);
hexinping123 2011-11-19
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 dencey 的回复:]
定义类的构造函数时,对原型(prototype)的定义要放在构造函数外部的,否则它只是构造函数的一项属性,而不是类的原型,所以不会被继承,
[/Quote]

3楼的朋友说的对,你把 “child.prototype=new father();”这句代码放到外面,你再画下原型链图,就明白了
默默不得鱼 2011-11-19
  • 打赏
  • 举报
回复
你写在function里时 还没有执行你的继承 child还是child
dencey 2011-11-19
  • 打赏
  • 举报
回复
定义类的构造函数时,对原型(prototype)的定义要放在构造函数外部的,否则它只是构造函数的一项属性,而不是类的原型,所以不会被继承,
wyman25 2011-11-19
  • 打赏
  • 举报
回复
“引擎在new的时候会先将prototype的引用放到实例中,然后再执行构造函数里面的code.”这是什么意思?可以再解析详细一点吗?或者配合一些代码解析一下,谢谢。还有就是liangws兄是在哪里学习到这点的?是js引擎的解析编译,还是js哪个特性?
JavaScript核心技术 简介: 《JavaScript核心技术》对于各种浏览器、浏览器版本、JavaScript版本、DOM版本的介绍,有助于我们理解所遇到的各种新旧代码,使我们能够对这些代码做出正确的取舍。《JavaScript核心技术》还提供了一些使用JavaScript的最佳实践。无论是新手还是老手,这些如何正确使用JavaScript的经验都能帮助他们养成良好的编程习惯。《JavaScript核心技术》还介绍了一些调试和开发JavaScript的工具,这些工具无疑能够提高我们的开发效率。 《JavaScript核心技术》最后对于Ajax和几个流行的JavaScript库的介绍,无疑会开阔我们在JavaScript使用上的思路。 《JavaScript核心技术》是一本真正意义上的“新书”,不仅介绍了最新的JavaScript知识和方向,还完全覆盖了当今Web开发中关于JavaScript的所有重要话题,它使用了大量实例代码,图文并茂地讲解了使用JavaScript的各个层次和领域的内容。它不是一本参考手册,但却是一本值得拥有的教程。 JavaScript核心技术 目录: 前言 第1章JavaScript初探 1.1规范和实现相互交织的历史 1.2跨浏览器的不兼容性和其他常见的JavaScript传说 1.3你能用JavaScript来做什么 1.4JavaScript初探:“HelloWorld!” 1.5JavaScript沙箱 1.6可访问性和JavaScript的最佳实践 第2章JavaScript数据类型与变量 2.1变量的标识 2.2作用域 2.3简单类型 2.4常量:有名称但不改变 2.5习题 第3章运算符和语句 3.1JavaScript语句的格式 3.2简单语句 3.3条件语句和程序流 3.4条件运算符 3.5逻辑运算符 3.6高级语句:循环语句 3.7习题 第4章JavaScript对象 4.1对象构造函数 4.2Number对象 4.3String对象 4.4正则表达式与RegExp 4.5有专门用途的对象:Date和Math 4.6JavaScript数组 4.7关联数组:不是数组的数组 4.8习题 第5章函数 5.1定义函数:细数所有方式 5.2回调函数 5.3函数和递归 5.4嵌套函数、函数闭包和内存泄漏 5.5作为对象的函数 5.6习题 第6章捕捉事件 6.1O级DOM上的事件句柄 6.22级DOM上的事件句柄 6.3产生事件 6.4习题 第7章表单与即时验证 7.1访问表单 7.2把事件附加在表单上:不同的方法 7.3选择列表 7.4单选按钮和复选框 7.5输入字段和JiT正则表达式 7.6习题 第8章沙箱及之上的cookie、连通性和隐私 第9章基础浏览器对象 第10章DOM:文档对象模型 第11章创建定制的JavaScript对象 第12章构建动态网页:在脚本中加入样式 第13章使用Ajax 第14章好消息:生动的程序库!令人惊异的Web服务!有趣的API! 附录习题答案

87,997

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧