为什么无法更改 JS 的构造函数呢?

2016-01-13 22:11:50 +08:00
 tianzhen
var Person = function(name) { this.name = name };
var foo = new Person("foo");
foo // { name: 'foo' }
foo.constructor.toString() // 'function (name) { this.name = name }'
Person.prototype.constructor.toString() // 'function (name) { this.name = name }'

// 改写 constructor 指向的构造函数
Person.prototype.constructor = function(name) { this.name = "bar" }

Person.prototype.constructor.toString() // 'function (name) { this.name = "bar" }'
var foo2 = new Person("foo2");
foo2.constructor.toString() // 'function (name) { this.name = "bar" }'

// 期待是 { name: 'bar' } 因为构造函数已变了
// 但是...
foo2 // { name: 'foo2' }
3000 次点击
所在节点    JavaScript
15 条回复
iwege
2016-01-13 22:18:13 +08:00
在最后试试 Person.toString() 看看。
Person 本来就是一个 function 了。 要改变的话直接赋值 Person = func 就好了。
tianzhen
2016-01-13 22:24:47 +08:00
@iwege 原来如此,貌似我那样做只是把 Person.prototype 对象给改写了

```javascript
// 原本
Person === Person.prototype.constructor // true
// 改写后
Person === Person.prototype.constructor // false
Person.toString(); // 依旧是 'function (name) { this.name = name }'
```
banricho
2016-01-14 00:58:56 +08:00
1. 函数都有 prototype 对象,其中默认包含一个属性 constructor ,一般情况下默认指向函数自身
2. 以你的例子来说, foo1. __proto__ === Person.prototype ,修改 constructor 是没有用的,它只是一个天生就默认存在的标志,但本身不具备实际意义
3. 你的任何实例化方法本身不存在 toString 方法,那么就会向构造函数 Person 上查找。没有的话就继续向 Function.prototype 上查找,还是没有就继续在 Function.prototype.__proto__ 也就是 Object.prototype 上查找,于是你里面所有的 toString 其实最终调用的都是 Object.prototype.toString 方法
4. 要达到你的效果修改 constructor 是没用的,关键是要在 foo1 和 foo2 之间切断原型链
banricho
2016-01-14 00:59:58 +08:00
@banricho “那么就会向构造函数 Person 上查找” => “那么就会向构造函数 Person.prototype 上查找”
banricho
2016-01-14 01:12:32 +08:00
我搞错了,请看下面的

var Person = function(name) {
this.name = name
};

var foo = new Person("foo");

console.log(foo.toString === Person.prototype.toString); // true
console.log(Person.prototype.toString === Person.prototype.__proto__.toString); // true
console.log(Person.prototype.__proto__.toString === Object.prototype.toString); // true

console.log(Person.toString === Function.prototype.toString); // true
console.log(Function.prototype.toString === Object.toString); // true

我上面说的第 3 点有误。。。
banricho
2016-01-14 01:20:35 +08:00
还得补上这个 = =。

console.log(Person.toString === Function.prototype.toString); // true
console.log(Function.prototype.toString === Object.toString); // true
console.log(Function.prototype.toString === Function.toString); // true
console.log(Function.toString === Object.toString); // true
console.log(Function.__proto__ === Object.__proto__); // true

好微妙的关系(好了我去睡了,大晚上脑子混乱又乱扯了。。。)
banricho
2016-01-14 04:02:49 +08:00
没睡着 =。= 爬起来**貌似**搞清了,直接上图

banricho
2016-01-14 04:08:44 +08:00
@banricho 我真去睡了
大晚上脑子果然不清醒

Function.prototype.__proto__ 指向的应该是 Object.prototype 而不是 Person 的。。。
啊啊啊啊啊啊啊啊 救命啊好丢人
banricho
2016-01-14 04:25:45 +08:00
补完睡觉,刷屏抱歉

starAsh
2016-01-14 09:29:24 +08:00
@banricho 能够见到这么认真的回复以及对技术的认真态度,小弟膜拜
tianzhen
2016-01-14 09:34:05 +08:00
@banricho Orz 膜拜!您的全部回复都给了感谢!
SpicyCat
2016-01-14 10:22:23 +08:00
@banricho 这图用什么工具画的,太厉害了
banricho
2016-01-14 10:29:50 +08:00
@starAsh 并没有认真啦,就是有点强迫症 >w<

@tianzhen 谢谢哈~~受宠若惊

@SpicyCat 用的是 iOS 上的 Paper 53 ,然后扔电脑上用了 Pixelmator 加了个字 -_- ||
SilentDepth
2016-01-14 13:22:52 +08:00
@banricho 正纳闷这浓浓的 Paper 感是怎么揉进文字的,原来还有后期……
banricho
2016-01-14 15:26:13 +08:00
@SilentDepth 哈哈哈
就是写字不方便,没文字总画错😂
准备入手个手写笔试试写字

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

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

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

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

© 2021 V2EX