一道关于原型的问题

tudewutong
  • 1.2k
var fun = function(){}

fun.prototype = {    
    name : 'peter',    
    age : 25    
}

var a = new fun();
var b = new fun();
console.log(a.name, b.name);//peter peter
fun.prototype.name = 'jack';
console.log(a.name, b.name);//jack jack
fun.prototype = {};
fun.prototype.name = 'tom';
console.log(a.name, b.name);//jack jack
b.constructor.prototype.name = 'kitty';
console.log(a.name, b.name);//jack jack
//输出些什么鬼?

fun.prototype = {};
fun.prototype.name = 'tom';

操作之后的输出很不理解,fun的prototype已经改变了,访问a的name属性,查找原型链不应该输出tom?
更新:
还有一个问题,由于fun.prototype = {}操作覆盖了原型,所以之后对fun.prototype的属性修改其实修改的是{}.于是把fun.prototype = {}操作去掉,代码如下:

var fun = function(){}

fun.prototype = {    
    name : 'peter',    
    age : 25    
}

var a = new fun();
var b = new fun();
console.log(a.name, b.name);//peter peter
fun.prototype.name = 'jack';
console.log(a.name, b.name);//jack jack
fun.prototype.name = 'tom';
console.log(a.name, b.name);//tom tom
b.constructor.prototype.name = 'kitty';
console.log(a.name, b.name);//tom tom
//输出些什么鬼?

b.constructor.prototype.name = 'kitty'这一步问什么没有生效呢

评论
阅读 3.7k
7 个回答
✓ 已被采纳

例一:

图片描述

例二:

图片描述

区别在于图1多了一句func.prototype = {}

你要知道一点,Object的赋值,其实都是引用。就懂了。

你可以试一下给出现过的object命名。

fun.prototype = {    
    name : 'peter',    
    age : 25    
} //A

所以a和b的 proto 指向 A

fun.prototype.name = 'jack';
此时fun.prototype也指向A,所以是A的name被修改了。

fun.prototype = {};//B
此时fun.prototype指向B

然而a,b依然指向A。

这里体现的其实是Object的引用性质

对于更新中:

b.constructor.prototype.name = 'kitty'这一步问什么没有生效呢

答案:

更改:

fun.prototype = {    
    name : 'peter',    
    age : 25    
}

为:

fun.prototype = {    
    constructor: fun,
    name : 'peter',    
    age : 25    
}

因为你给 prototype 赋值了一个新的对象的引用,所以原来的原型链被切断了。默认情况下 fun.prototype.constructor 的值为 fun

yiliashaw
  • 2
新手上路,请多包涵

1).prototype ={}是重写原型,重写后跟重写前就已经实例化的对象没有关系的,所以Tom自然不生效。
2)但你之前实例化的对象的constructor仍然是Fun,Fun的prototype.name=“Kitty”相当于你把name属性添加到重写后的原型里,由于1)的原因自然不生效咯。

对象在创建的时候原型链就已经定下来了,

fun.prototype={};
fun.prototype.name='tom';

这时候fun.prototype是一个新的对象,而a和b的__proto__依旧是之前的fun.prototype所以输出的就是jack。
如果你在后边在后边在新实例化出一个对象,这个新的对象中的属性就会继承自新的原型中的属性了

var c=new fun();
console.log(c.name)//tom

这种吗?应该是b指向的原来的原型

其实这个很简单
1.fun.prototype={},原型链是引用的,之后切断了,之后的设置肯定不行
2.吧fun.prototype={}去掉后,为什么b.constructor.prototype.name = 'kitty'这句话不起作用,那是因为b.constructor != fun. 而设置原型链,只能设置fun.prototype或者设置a.__proto__等,只要能把值设置在原型链上,都是没有问题的,通过引用原理,就能赋值

宣传栏