有关 JavaScript 中实例的 constructor 属性的问题。

2015-05-31 16:42:06 +08:00
 haozhang
function A () {};
function B () {};
B.prototype = new A();
var a = new A();
var b = new B();
log(a.constructor); // A
log(b.constructor); // A

js中实例是有一个constructor属性指向它的构造函数的。
如上面的A类的实例a,它的constructor属性就指向A。
但是当B继承了A之后,B的实例b的constructor指向的却不是B类,而是父类A。

4122 次点击
所在节点    JavaScript
48 条回复
CoooolChan
2015-05-31 18:45:03 +08:00
函数有prototype属性指向原型对象
原型对象有constructor属性,指向构造函数
实例内部有[[Protype]]指向原型对象
实例的属性访问,先看实例自己有没有,有就返回,没有就沿着原型对象找
A什么都没做,constructor指向A
B的protype被重写了,此时指向的是A的实例,b.constructor先查实例,没找到,再查原型对象(A的实例),没找到,继续找A的原型对象,找到了A.constructor=构造函数A
ibigbug
2015-05-31 19:19:23 +08:00
@haozhang 说错了。。 改成 B 。。
haozhang
2015-05-31 19:56:47 +08:00
@CoooolChan 是[[Prototype]]...
Biwood
2015-05-31 22:19:50 +08:00
JavaScript 中的所有对象都可以看作是 Object 对象的实例,因此所有对象都继承了 Object.prototype 上的方法和属性,所以,所有对象都有 constructor 这个属性,《JavaScript 高级程序设计》这本书上的说法是没有问题的,实例也是对象,原型对象也是对象,凡是 JavaScript 中的对象都有 constructor 属性,没有任何问题。
FrankFang128
2015-05-31 22:25:13 +08:00
用 console.dir() 既知
Mutoo
2015-05-31 22:36:32 +08:00
话说原型的 constructor 这个属性有啥用?(然而并没有什么卵用。)
haozhang
2015-05-31 22:39:24 +08:00
@Biwood 但是它没有指出这玩意是继承来的,而不是自带的...两个方式产生的结果完全不同,就像我一直以为这个属性是自带的,所以才会问出这个问题。
haozhang
2015-05-31 22:40:04 +08:00
@Mutoo 用来对实例进行类型判断。
Mutoo
2015-05-31 22:43:13 +08:00
@haozhang 这东西没有 instanceof 靠谱吧,毕竟可以随意修改。
Biwood
2015-05-31 22:44:54 +08:00
我用词有误, Object 是构造函数,不是对象,所有的构造函数都有 prototype 属性,prototype 里面存放的是构造函数创建的所有实例的原型对象,所有实例可以共享原型对象的属性 (properties) 和方法 (methods) ,constructor 就是所有实例共享的属性之一。
Biwood
2015-05-31 22:45:17 +08:00
@haozhang 实例和实例的原型对象是紧密关联的,原型对象所拥有的,相对的实例也必然也有,所以不存在 constructor 属于哪一个的说法。
如果按你的补充中的思路来看,JavaScript 中只有 Object.prototype 有 constructor 属性,其他对象都只是继承而已。
Biwood
2015-05-31 22:58:26 +08:00
所谓原型就是指一个对象最初始的样子,构造函数就像一台机器(或者说一个加工厂),不断的照着原型对象的样子来生产对象,生产出来的对象都是照着 [原型对象] 的模子做的,当你把 prototype 重写了,那么 [原型对象] 的模子也变了,所以构造函数会照着新的模子来生产对象,只不过这个新的模子也是照着另外的模子被生产出来的,所谓继承,就是这么实现。
haozhang
2015-05-31 23:00:34 +08:00
@Biwood 你说了很多...但是这个问题仅仅就是constructor是继承来的还是自带的而已...来个方式带来两个结果...显然《js高程》的叙述并不严谨...
Biwood
2015-05-31 23:03:12 +08:00
@haozhang 我说了很多是因为我也需要自己理清一下思路,之前我的理解并不算清晰,就着你的问题,我愿意捋一捋之前所学的知识 :)
haozhang
2015-05-31 23:04:36 +08:00
@Biwood →_→ 我花了半年刷完《js高程》,然而并没有什么卵用...
joyee
2015-05-31 23:07:15 +08:00
因为

function B () {}; // B.prototype.constructor === B
B.prototype = new A(); // B.prototype.__proto__.constructor === A

另外其实想知道每一步执行之后A和B的原型链都是什么模样可以用console啊……Chrome的不太好用,Firefox的可以看得很清楚,执行完之后点击A或者B看右边会列出所有的东西
haozhang
2015-05-31 23:10:47 +08:00
@joyee 直接说constructor是继承来的不就得了...
joyee
2015-05-31 23:14:33 +08:00
@haozhang 其实我一直觉得在JavaScript的范围里说继承是件挺奇怪的事……就是搭原型链而已,说继承联想到普通的OO反而更迷惑
Biwood
2015-05-31 23:18:40 +08:00
@haozhang 继承来的也就是自带的不是么,总不能凭空出现吧,打个通俗的比喻,一个男孩继承了他父亲一样的棕色的眼镜,但这双眼睛是男孩自己的不是别人的,只是眼睛的颜色恰好跟他父亲的眼睛的颜色一样叫“棕色”。上面所说的 constructor 就是这个“棕色”一样的东西。
haozhang
2015-05-31 23:20:16 +08:00
@joyee 因为习惯了继承...

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/195097

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX