【问题标题】:Why use object.prototype.constructor in OOP javascript?为什么在 OOP javascript 中使用 object.prototype.constructor?
【发布时间】:2012-02-22 21:04:03
【问题描述】:

我最近开始阅读 OOP javascript,作者似乎跳过的一件事是,当对象 A 被声明时,我突然看到“A.prototype.constructor =A; 例如,

var A = function(){}; // This is the constructor of "A"
A.prototype.constructor = A;
A.prototype.value = 1;
A.prototype.test = function() { alert(this.value); }
var a = new A(); // create an instance of A
alert(a.value);  // => 1

所以我在 firebug "var A = function(){};" 中运行命令 然后是“A.Constructor”,它揭示了它是一个函数。我明白这一点。
我运行代码“A.prototype.constructor = A;”我认为这会将 A 构造函数从 Function 更改为 A。

A 的构造函数属性已经改变了吧?相反,当我运行“A.constructor”时,它仍然给我函数()。

有什么意义?

我也看到了 A.constructor.prototype.constructor.prototype.. 这是怎么回事?

【问题讨论】:

标签: javascript oop


【解决方案1】:

如果 A 使用 A.prototype = new B(); 继承 B,则需要使用 A.prototype.constructor=A; 重置类 A 的构造函数属性,否则 A 的实例将具有 B 的构造函数。

在你的情况下,A.prototype.constructor === A 将返回 true,所以 A.prototype.constructor = A 什么也没做。

【讨论】:

  • 很有趣,所以 A.prototype.constructor=A;会使 A 与 B 隔离开来吗?这样,您可以使用 A.prototype 扩展更多属性,而无需向 B 添加更多属性?
  • 隔离无关,只是确保 A 具有正确的构造函数属性。
  • 拥有正确的构造函数属性的目的是什么? A.prototype.constructor 什么时候在实践中实际咨询过?它似乎不影响创建 A, afaics 的新实例的行为。答案必须如此明显,以至于通常没有说明,这就是为什么它一直躲避我:-)
【解决方案2】:

您可以快速测试该额外分配绝对没有任何作用:

var A = function() {};
A.prototype.constructor === A; // true -- why assign then?

只有当你为类分配了一个新的原型对象,覆盖了原来的构造函数时,重置构造函数属性才有意义:

var A = function() {};
A.prototype = protoObject; // some object with members that you'd like to inherit
A.prototype.constructor = A; // reset constructor

在您的情况下,作者可能会盲目地将其作为一种良好做法,即使在没有必要的情况下也是如此。

【讨论】:

    【解决方案3】:

    这段代码如果经常在 JS 经典继承模式中使用(代码来自 Stoyan Stefanov 的 JavaScript Patterns):

    function inherit(C, P) { 
        var F = function () {}; 
        F.prototype = P.prototype; 
        C.prototype = new F(); 
        C.uber = P.prototype; 
        C.prototype.constructor = C; 
    } 
    

    将正确的构造函数分配给子类。

    在你的情况下,它什么也没做,因为在分配之前A.prototype.constructor === A

    【讨论】:

      【解决方案4】:

      你可能想看看我对类似问题的回答:

      https://stackoverflow.com/a/19616652/207661

      TL;DR:构造函数不是实例的自有属性。因此,为了让事情看起来一致,JavaScript 解释器需要设置 prototype.constructor 来运行自己。此功能可用于对许多不同类型的对象进行通用操作的函数中。

      【讨论】:

        【解决方案5】:

        根据 MDN,所有对象都从其原型继承构造函数属性:

        Example 1:
        var o = {};
        o.constructor === Object; // true
        

        ..

        Example2:
        function Tree() {  
        }    
        var theTree = new Tree();
        console.log(theTree.constructor === Tree ); // true
        

        在运行时,它不会根据构造函数属性的值产生任何影响。

        但是,由于构造函数属性返回对创建实例原型的 Object 函数的引用,因此在将新原型分配给 Object 函数时应该重置构造函数属性。

        var Forest = function() {};
        Forest.prototype = theTree;  
        console.log(new Forest().constructor === Tree ); // true
        Forest.prototype.constructor = Forest;  
        console.log(new Forest().constructor === Forest ); // true
        

        https://jsfiddle.net/j1ub9sap/

        详情:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor

        【讨论】:

        • 嗨,几个月后我开始评论你的评论,因为我不明白这句话:“但是,作为构造函数属性返回对创建实例原型的对象函数的引用”对象函数不创建实例的原型,它直接创建实例不?究竟是什么意思?谢谢
        • 表示如果 Forest 使用 Forest.prototype = new theTree() 继承 theTree,Forest 的实例将具有 theTree 的构造函数。要将 Forest 作为构造函数,需要使用 Forest.prototype.constructor=Forest 重置 Forest 的构造函数属性。
        • 我理解你的例子。我的问题更多关于官方文档:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 它说“返回对创建实例原型的 Object 函数的引用。”。但是,此页面中的所有示例都没有覆盖其原型。没有自定义继承:var a = []; a.constructor === Array; 那么为什么不说“构造函数是对创建实例本身的 Object 函数的引用”?谢谢
        猜你喜欢
        • 1970-01-01
        • 2016-10-08
        • 2011-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-23
        • 2010-10-17
        相关资源
        最近更新 更多