我在学习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版的积分不多,请不要嫌弃
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版的积分不多,请不要嫌弃
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);
3楼的朋友说的对,你把 “child.prototype=new father();”这句代码放到外面,你再画下原型链图,就明白了
代码改一下
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);
首先,当浏览器执行到“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>
然后执行完这些后,再执行接下来的构造函数里面的代码,也就是“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);
第一次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属性。
算了,结贴。