【问题标题】:Javascript functions overriden prototypeJavascript函数覆盖原型
【发布时间】:2013-04-06 07:00:56
【问题描述】:

我在 SO 上找到了一些有趣的例子。其中包括指向此article 的链接。 据说:

Function.__proto__ 指向Function.prototype。这导致:

 Function.constructor === Function

也就是说:函数是它自己的构造函数!

Object instanceof Object == true.

这是因为:

Object.__proto__.__proto__.constructor == Object 

另请注意,与Object instanceof ObjectFoo instanceof Foo == false 不同。 这是因为:Foo 不作为它自己的原型链的构造函数存在。

从 Mozilla 开发者网络中,我发现原型和构造函数都可以很容易地被覆盖。由于instanceof 只是在原型链中检查constructor.prototype,我真的不明白为什么我的代码仍然返回false

function Foo() { } ;
Foo.prototype = Foo
Foo.constructor = Foo
Foo instanceof Foo // still false

还有一些关于原型的问题。我做对了吗,原型本身是一个单独的辅助对象?而这个对象就像另一个对象上的指针——通常是Object

【问题讨论】:

    标签: javascript oop function object prototype


    【解决方案1】:

    obj instanceof 不在obj.prototype 中查找constructor,而是在对象的内部__proto__ 属性中查找。

    javascript 中的每个对象都有一个内部__proto__ 属性,它引用对象的原型。当使用new 运算符构造对象时,该对象的内部__proto__ 属性将设置为构造函数的prototype 属性。

    因此,当您说Foo instanceof Foo 时,javascript VM 将在Foo.__proto__ 中查找“Foo”。因为 Foo 是一个函数,所以Foo.__proto__Function.prototype(其中Function 是函数的构造函数)。

    由于您实际上无法更改对象的内部 __proto__ 属性,因此 Foo 永远不能是 Foo 的实例。


    关于你的小问题:在 javascript 中,一切都是对象。这包括原型函数。事实上,ECMAScript 5 添加了一个函数Object.create (MDN),它以一个对象作为其第一个参数,然后使用第一个对象作为其内部原型对象创建一个新对象。

    【讨论】:

    • 嗯...有人能告诉我如何将粗体 proto 变成 _ _ proto _ _ 吗?
    • 抱歉,答案重叠,你的答案很好。我不知道如何逃避粗体降价,除了将它包装在代码段中,就像你在前面的回答中所做的那样。
    • 感谢您的回答,确实如此。我尝试更改 __proto__ 并显示 JS VM 和对象循环错误。
    • @Johnny_D __proto__ 链永远不会是循环的。如果您在对象中查找属性(例如obj.value)但该属性不存在,则会在对象的__proto__ 中查找。如果该属性也不存在,则查找__proto__.__proto__,直到找到该属性或__proto__ 为空。对于循环原型链,这将导致无限递归。
    • 同意,但在 Function 对象的情况下它以某种方式被处理了
    【解决方案2】:

    重要的是要记住,作为原型链一部分的对象的实际内部原型引用与对象的原型属性不同。对象的内部原型设置为其构造函数的原型property

    我在学习时发现最容易理解的文章实际上是this one

    换句话说,更改对象的prototype 属性的唯一要点是该对象是否是应用作构造函数的函数。除此之外,它没有什么神奇之处,它只是一个属性。更改 prototype 不会更改 __proto__ 并且不会影响对象的原型链。

    所以,通过代码:

    function Foo() {}
    

    此时Foo的构造函数实际上是Function,Function.prototype是Foo的实际内部原型,或者__proto__,如果你愿意的话。

    Foo.prototype = Foo;
    

    这只会改变 Foo 的原型属性,而不是它的内部原型。

    Foo.constructor = Foo
    

    这实际上只是在 Foo 上设置 constructor 属性,它对 Foo.prototype.constructor 没有任何作用,它也不对 Foo 的内部原型的构造函数做任何事情,这是 instanceof 检查的。


    试试这个代码序列,希望它会更清楚一点:

    function Foo() { } ;
    
    (Foo.prototype != Function.prototype && Foo.__proto__ == Function.prototype);
    
    Foo.prototype = Foo;
    
    (Foo.prototype == Foo && Foo.__proto__ != Foo && Foo.__proto__ == Function.prototype);
    
    Foo.constructor = Foo;
    
    (Foo.constructor == Foo && Foo.prototype.constructor == Foo && Foo.__proto__.constructor != Foo);
    

    【讨论】:

    • 感谢文章和 cmets,现在它对我来说看起来更整洁了。
    • 看来你最后的例子应该是Foo.prototype.constructor == Foo
    • 好的,谢谢。除非显式更改,否则函数的原型构造函数始终是函数本身。
    猜你喜欢
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    • 2014-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多