【问题标题】:JavaScript: how to access the prototype of a constructor function?JavaScript:如何访问构造函数的原型?
【发布时间】:2011-10-28 19:23:25
【问题描述】:

对于 JS 大师和忍者来说可能是个愚蠢的问题,但这里是:

我对对象的原型对象/属性的理解是,它是对象未来实例的蓝图。鉴于此,新创建的对象实例不应该与创建它的构造函数对象相同吗?

var x = new Object(); 
console.log(x === Object.prototype); // returns false. why?? 

* 更新 *

所以理解这将返回 false 因为它们引用了不同的东西,我仍然发现 new Object() 和 Object.prototype 包含不同数量的属性。所以要细化我的问题:如何正确检查原型对象中的属性数量;我如何遍历它们?

我对此感到困惑的原因是,如果我创建一个简单的构造函数:

function Circle(){
   this.tail = "yes, has tail";
}

并想获取它拥有的属性数量,例如:

console.log(Object.getOwnPropertyNames(Circle.prototype)); 
// returns "constructor", I expected it to return "tail"

【问题讨论】:

    标签: javascript object constructor prototype-programming


    【解决方案1】:

    === 没有回答两个事物是否等价的问题,而是他们是否是对同一个对象的引用。

    您的示例中的xObject.prototype 可能具有相同的属性,因此您可以称它们为等价,但它们是两个不同的对象。

    如果你这样做

    x.foo = 3
    

    它们现在不再等价,因为它们是两个不同的对象。你改变了一个,但没有改变另一个。

    如果

    x === Object.prototype
    

    是真的,那么

    x.foo === Object.prototype.foo
    

    无论您将什么分配给x.fooObject.prototype.foo,都将是相同的。

    编辑:

    function Circle(){ this.tail = "yes, has tail"; }
    
    console.log(Object.getOwnPropertyNames(Circle.prototype)); 
    // returns "constructor", I expected it to return "tail"
    

    Circle.prototype 上没有 tail 属性,因为您从未做过 Circle.prototype.tail = ...;。您仅在 Circle instances 上通过 this.tail = ...; 定义 tail

    我仍然发现new Object()Object.prototype 包含不同数量的属性。

    你也在做getOwnPropertyNames自己的属性是那些没有从原型继承的属性,因此通过在x 上使用该函数,您明确排除了Object.prototype 的所有属性。

    hasOwnProperty 的文档很好地解释了“自己的财产”:

    该方法可用于判断一个对象是否具有指定属性作为该对象的直接属性;与in 运算符不同,此方法不会检查对象的原型链。

    【讨论】:

      【解决方案2】:

      console.log(Object.getPrototypeOf(x) === Object.prototype); // true

      如果您想获取指向对象原型链中下一个元素的隐藏属性[[Prototype]],只需调用Object.getPrototypeOf

      你也误解了原型链的工作原理。

      对于任何给定的对象,如果您查找一个属性,它将首先查看该对象。然后它将(递归地)查看对象[[Prototype]] 的值是否具有该属性。

      示例原型链:

      var o = new Object();
      // o -> Object.prototype -> null
      var a = new Array();
      // a -> Array.prototype -> Object.prototype -> null
      var Super = function () {};
      var Child = function () {};
      Child.prototype = Object.create(Super.prototype);
      var c = new Child();
      // c -> Child.prototype -> Super.prototype -> Object.prototype -> null
      

      【讨论】:

        【解决方案3】:

        x 是“对象”的一个实例。您可能想检查 x 是否有一个 Object 作为构造函数。原型不是构造函数。 试试这个

        var x = new Object(); 
        console.log(x.constructor === Object);
        

        【讨论】:

        • .constructor 是事实上的标准。有些人忘记使用.constructor,这样的逻辑就会崩溃。
        【解决方案4】:

        关于您的更新:

        构造函数中的this 是使用new 关键字创建的实例,而不是prototype

        所以,对于你的 sn-p...

        function Circle(){
           this.tail = "yes, has tail";
        }
        

        设置this.tail类似于:

        var c = new Circle();
        c.tail = "yes, has tail";
        

        tail 只是实例的一个属性。

        要在prototype 上设置tail,您必须使用:

        Circle.prototype.tail = "yes, has tail";
        

        现在,“Own”属性是直接在实例上设置的属性。这些计数器和覆盖prototype 的同名属性:

        function Circle() {
            // give the instance its "own" `foo` property
            this.foo = 'qux';
        }
        
        Circle.prototype.foo = 'foo';
        Circle.prototype.bar = 'bar';
        
        var c = new Circle();
        
        console.log(c.foo); // the overridden "qux", not the inherited "foo"
        console.log(c.bar); // "bar", as inherited
        
        // yet the prototype still persists to have its "own" `foo`
        console.log(Circle.prototype.foo); // "foo"
        
        // While the instance has keys for all involved properties
        console.log(Object.keys(c)); // [ "foo", "bar" ]
        
        // It also retains which are its "own"
        console.log(Object.getOwnPropertyNames(c)); // [ "foo" ]
        

        【讨论】:

        • 啊,我明白了,谢谢,我以为当你创建一个构造函数时,原型就是构造函数定义的任何东西的副本。
        猜你喜欢
        • 1970-01-01
        • 2016-05-16
        • 2020-07-11
        • 1970-01-01
        • 2017-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多