V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
tianzhen
V2EX  ›  JavaScript

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

  •  
  •   tianzhen · 2016-01-13 22:11:50 +08:00 · 3158 次点击
    这是一个创建于 3235 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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' }
    
    15 条回复    2016-01-14 15:26:13 +08:00
    iwege
        1
    iwege  
       2016-01-13 22:18:13 +08:00   ❤️ 1
    在最后试试 Person.toString() 看看。
    Person 本来就是一个 function 了。 要改变的话直接赋值 Person = func 就好了。
    tianzhen
        2
    tianzhen  
    OP
       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
        3
    banricho  
       2016-01-14 00:58:56 +08:00   ❤️ 1
    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
        4
    banricho  
       2016-01-14 00:59:58 +08:00   ❤️ 1
    @banricho “那么就会向构造函数 Person 上查找” => “那么就会向构造函数 Person.prototype 上查找”
    banricho
        5
    banricho  
       2016-01-14 01:12:32 +08:00   ❤️ 1
    我搞错了,请看下面的

    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
        6
    banricho  
       2016-01-14 01:20:35 +08:00   ❤️ 1
    还得补上这个 = =。

    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
        7
    banricho  
       2016-01-14 04:02:49 +08:00   ❤️ 1
    没睡着 =。= 爬起来**貌似**搞清了,直接上图

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

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

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

    @tianzhen 谢谢哈~~受宠若惊

    @SpicyCat 用的是 iOS 上的 Paper 53 ,然后扔电脑上用了 Pixelmator 加了个字 -_- ||
    SilentDepth
        14
    SilentDepth  
       2016-01-14 13:22:52 +08:00
    @banricho 正纳闷这浓浓的 Paper 感是怎么揉进文字的,原来还有后期……
    banricho
        15
    banricho  
       2016-01-14 15:26:13 +08:00 via Android
    @SilentDepth 哈哈哈
    就是写字不方便,没文字总画错😂
    准备入手个手写笔试试写字
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4118 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 94ms · UTC 04:10 · PVG 12:10 · LAX 20:10 · JFK 23:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.