Object.getOwnPropertyNames中的混淆问题

4

您好,以下是代码翻译:

   function employee()
    {
     this.name="john";
    }

    employee.prototype={
      job:"manager",
      projects:["sales","training","construction"],
      display:function()
      {
       alert(this.name+" is a "+ this.job);
      }
    }

    var property=Object.getOwnPropertyNames(employee.prototype);
    alert(property);

我得到的结果是工作、项目、显示,但当我使用原型定义属性时,就像这样:

function employee()
    {
     this.name="john";
    }

    employee.prototype.job="manager";
    employee.prototype.projects=["sales","training","construction"];
    employee.prototype.display=function()
    {
     alert(this.name+"is a"+ this.job);
    }


 var property=Object.getOwnPropertyNames(employee.prototype);
 alert(property);

我得到的结果是构造函数、工作、项目和显示。

我的问题是为什么在第一种情况的结果中没有获得构造函数?


我的回答能够为您提供所需的信息吗?如果没有,需要补充什么内容? - shmuli
我更新了我的回答,并对你的第一个片段进行了更正。 - shmuli
@DanPrince 这篇文章涉及将对象字面量分配给原型,以及如何使用全局Object覆盖构造函数对象。这个问题涉及非常不同的代码、不同的副作用和当然 - 不同的答案。我必须不同意你关于可能重复的看法。 - shmuli
哎呀,看来我忘记在你的 alert() 中加入 console.log() 了。我已经把它改回来了,现在应该可以正常工作了。 - shmuli
2个回答

2
当您声明 employee 函数时,它实例化了一个Function实例,其 prototype 包含指向该函数的" constructor "属性。将新属性分配给原型将会保留它。因此,使用 new employee 创建的对象将继承这个" constructor "属性,以说明它们是由什么构建而成的。
function C(){}
console.log(C.prototype.constructor) // returns C
console.log(C.prototype.hasOwnProperty("constructor") // true

cosole.log(new C().constructor) // C
cosole.log(new C().hasOwnProperty("constructor") // false, it's inherited

然而,当你覆盖整个prototype时,也会删除constructor属性。对象当然有一个构造函数(Object),但它是继承的,所以不会显示为“OwnProperties”。


0
当你将一个对象分配给原型时,它会改变该对象的原型继承。由于在第一个示例中,您直接将对象分配给原型,因此对象本身被分配到原型上。这会覆盖对象原型上的employee 构造函数,并用全局Object对象替换它。这就是发生了什么的关键。

您可以通过将此代码行放入第一个实现中来验证构造函数是否已被覆盖:

console.log(employee.prototype.constructor === Object); // returns: true

正如您所看到的,它返回true - 验证了您的employee.prototype的构造函数不是您期望的(它将设置为自身... employee),而是全局Object对象。

由于构造函数现在设置为全局Object,因此getOwnPropertyNames方法不会在employee对象属性中检索它。 getOwnProperyNames方法仅检索属于该对象本身的方法 - 而不是继承的对象

您可以通过添加一行来更正第一个片段,如下面代码所示:

function employee() {
     this.name = "john";
   }

   employee.prototype = {
     constructor: employee, // <--- ADD THIS LINE
     job: "manager",
     projects: ["sales", "training", "construction"],
     display: function() {
       alert(this.name + " is a " + this.job);
     }
   };

   var property = Object.getOwnPropertyNames(employee.prototype);
   alert(property);

这将重置您对象原型的构造函数,并且现在它也将返回constructor

值得注意的是,以这种方式还原构造函数会创建一个enumerable属性,其值为true。原生构造函数默认情况下不可枚举。因此,如果您使用的是ES5,则可能更喜欢以以下方式还原构造函数:

Object.defineProperty(employee.prototype, 'constructor', {
enumerable: false,
value: employee
});

注意:此代码片段必须放置在employee.prototype = {//code};之后。否则它将被再次覆盖。

更多阅读:http://javascript.info/tutorial/constructor

https://codereview.stackexchange.com/questions/62402/javascript-constructor-and-namespace-in-object-literal-style/86222#86222


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接