V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
pythonee
V2EX  ›  程序员

javascript实例对象的constructor属性值是怎么来的?

  •  
  •   pythonee · 2013-07-11 17:57:02 +08:00 · 3423 次点击
    这是一个创建于 4146 天前的主题,其中的信息可能已经有所发展或是发生改变。
    疑惑来源于我做的一个实验,实验过程如下:

    > function Foo(){};
    > var f1 = new Foo();
    > f1.constructor

    这里能按期待的输出,也就是 Foo() 函数本身,但是如果我更改Foo.prototype属性,就有点奇怪了

    > Foo.prototype = {};
    > var f2 = new Foo();
    > f2.constructor

    这时候输出

    function Object() { [ native code] }

    我就开始猜想,
    instance.constuctor === instance.__proto__.constructor

    接着实验,把构造器的prototype指到Function()实例,看看什么情况
    > Foo.prototype = new Function();
    > var f3 = new Foo();
    > f3.constructor

    这时候按猜想,f3.__proto__ == Foo.prototype 也即 new Function(); 而
    new Function().constructor就是function Function() { [ native code] },实际输出和猜想吻合。


    再来点极端的,如果instance.__proto__ = null, 是个什么情况?

    > f3.__proto__ = null;

    这时候f3不再具备constructor属性!! 而typeof(f3)还是object,可是一个object既然没有constructor!!看起来猜想是正确的,但是这些是为什么呢?希望各位大牛指点,或者我的思路有什么问题没有?
    11 条回复    1970-01-01 08:00:00 +08:00
    switch
        1
    switch  
       2013-07-11 19:12:15 +08:00
    可以查看 ECMAScript 5,裡面定義了 typeof 是如果返回值的。
    pythonee
        3
    pythonee  
    OP
       2013-07-11 22:02:57 +08:00
    @guchengf

    有点乱了,实例的constructor也可以乱改,但是instanceof却是用最初创建它的来判断真假,这里谁记录最初创建它的构造器的呢?这样的话 instance.constructor也未必等于instance.__proto__.constructor,不过如果你不改的话,两者却是相等的,文档第一句话也确实这么说

    Returns a reference to the Object function that created the instance's prototype.
    otakustay
        4
    otakustay  
       2013-07-11 23:19:52 +08:00
    一个函数建立的时候,就有.prototype.constructor指向函数本身
    你改了prototype,新的prototype上没有constructor,因此f2.constructor在f2上没有,在Foo.prototype上也没有,就会再向上找Object.prototype上,在好运边能找到,因此就是Object这个东西
    pythonee
        5
    pythonee  
    OP
       2013-07-12 09:54:45 +08:00
    @otakustay 你说的原因和我想的一样,但是结果却不一样,函数建立的时候
    确实是
    function == function.prototype.constructor,而这时候由这个function创建的instance有以下关系
    instance.constructor == instance.__proto__.constructor
    又有
    instance.__proto__ == function.prototype
    所以
    instance.constructor == function.prototype.constructor
    如果我修改function.prototype,比如上面的f2,即Foo.prototype = {};所以
    f2.constructor = {}.constructor,
    而{}.constructor == Object.prototype.constructor,也即是Object(){ [native code]}
    而这后面的结果你的顺藤摸瓜式想法不一样啊
    otakustay
        6
    otakustay  
       2013-07-12 10:00:48 +08:00
    @pythonee 我们的结果是一样的啊,最后都是追溯到Object.prototype.constructor,即Object本身,Object本身就是Object() { [native code] }

    原型链的查找用一句话概括,就是“自己没有找自己原型,原型没有找原型的原型”,因此过程是

    f2.constructor(没有) -> f2.__proto__(就是Foo.prototype).constructor(没有) -> f2.__proto__.__proto__(就是Object.prototype).constructor(有) -> Object
    pythonee
        7
    pythonee  
    OP
       2013-07-12 10:01:06 +08:00
    @otakustay 而且我试验了,发现并没有顺着原型链来找构造函数这个说法啊
    otakustay
        8
    otakustay  
       2013-07-12 10:51:45 +08:00
    @pythonee constructor就是一个普通的属性,任何属性都是通过原型链来找的,没有例外,不是很理解你是怎么得了“没有顺着原型链”这个结论的……
    pythonee
        9
    pythonee  
    OP
       2013-07-12 11:37:46 +08:00
    @otakustay

    我的求值过程是代入,而不是顺着原型链,

    f2.constructor(有) == f2.__proto__(就是Foo.prototype).constructor(有) == {}.constructor(有) == Object.prototype.constructor == Object(){[native code]}

    我认为constructor是特殊的属性,而不是普通的
    otakustay
        10
    otakustay  
       2013-07-12 11:43:40 +08:00
    @pythonee
    是这样的,f2.__proto__.constructor === {}.constructor,但是{}.constructor是怎么来的呢?{}本身没有constructor(这个是肯定的,你用({}).hasOwnProperty('constructor')试),所以是({}).__proto__.constructor,也就是Object.prototype.constructor,所以还是顺着上去的

    所谓“有”还是“没有”,是用.hasOwnProperty('constructor')来检测的,因此在每一级试下这个方法就行了

    一种证明他是“顺着找”的方法是

    var f2 = new Foo();
    console.log(f2.constructor); // function Object() { [native code] }
    Object.prototype.constructor = 'fuck';
    console.log(f2.constructor); // 'fuck'
    pythonee
        11
    pythonee  
    OP
       2013-07-12 13:33:47 +08:00
    @otakustay

    如果这样定义"有"和"没有"的话,那从一开始f2.contructor就是没有的,可是如果按contructor的定义出发的我,是有的,所以,我觉得我们的分歧点在这里,不过我也能接受你的观点
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2613 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:00 · PVG 19:00 · LAX 03:00 · JFK 06:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.