javascript两个同名的变量共存于同一个对象中?

时间:2013-09-15 10:17:20

标签: javascript prototype

我正在尽力理解javascript。以下是Chrome控制台中的一个简单实验,让我非常困惑:

var foo=function(){this.p=1;}
foo.prototype.p=2;
var bar=new foo();
//foo{p:1,p:2} <- this is the output of Chrome console, from the last command above

Chrome的输出让我感到困惑。看起来bar是一个带有2个参数的对象,p:1和p:2。这意味着吧有2个???这背后的原因是什么?

5 个答案:

答案 0 :(得分:2)

bar对象只有一个值为1的p

可以在只读对象中查看值为2的早期p,您可以使用getPrototypeOf访问该对象:

Object.getPrototypeOf(bar).p

您可以看到两者,因为开发人员工具栏旨在打印指定对象的XML表示,该表示应直观地显示所有属性,无论是否可直接访问。

答案 1 :(得分:2)

是。排序。

bar同时具有:

  • ownp属性。

    bar.hasOwnProperty('p'); // true
    bar.p;                   // 1
    
  • p属性仍然是on the prototype 通过继承。

    Object.getPrototypeOf(bar).p; // 2
    

但是,一次只能从bar直接访问其中一个,而不是拥有属性。

bar.p;        // 1
delete bar.p;
bar.p;        // 2

而且,Chrome正在展示它们,因为它正在遍历prototype chain并寻找任何可枚举的属性。

答案 2 :(得分:2)

Chrome DevTools控制台的内联(非扩展)对象表示当前不显示自有属性和继承的原型属性之间的任何差异。

现在让我们把正在发生的事情分解成更小的步骤。

new foo()创建一个新对象,其内部proto属性指向foo.prototype。这意味着此对象可以访问foo.prototype中定义的所有属性。它被称为prototype chain

现在,当你在对象中设置一个同名的属性时,它会以相同的名称“隐藏”原型的属性,通过常规的属性访问使后者无法访问(请参阅@ loxxy使用Object.getPrototypeOf(obj)的答案进行访问阴影原型属性)。

向对象或其原​​型添加函数后,控制台允许您显示扩展对象表示,该表示与原型属性的属性不同。在下一个示例中,我向原型添加了q方法以允许此行为。从原型继承的属性显示在对象的proto内部属性中:

enter image description here


如果您只想在构造函数的原型中拥有实例化对象的数量,可以使用:

var foo = function() {
    Object.getPrototypeOf(this).p++;
}
foo.prototype.p = 0;

console.log(new foo()); //{p: 1}
console.log(new foo()); //{p: 2}

或没有ES5依赖:

var foo = function() {
    foo.prototype.p++;
}
foo.prototype.p = 0;

console.log(new foo()); //{p: 1}
console.log(new foo()); //{p: 2}

答案 3 :(得分:1)

var foo=function(){this.p=1;}是构造函数,在var bar=new foo();之后执行。所以在开始时p = 2然后p变为1.所以:

var foo=function(){
   // here this.p is equal to 2
   this.p=1;
   // here this.p is equal to 1
}
foo.prototype.p=2;
var bar=new foo();

编辑:

JSON.stringify(bar);

答案 4 :(得分:1)

当您访问属性时,javascript引擎将在对象实例上搜索它,然后在其所有原型链上搜索它 因此,p作为原型属性的含义是具有p的默认值,您是否在该类的任何实例上定义它。一个例子可能是车辆的车轮数量,例如可以默认为4 如果以后你写这个属性:

 function Vehicle() {};
 Vehicle.protoype.wheelCount = 4;
 var myBike = new Vehicle();
 myBike.wheelCount = 2 ;           // this is a bike.

您不会更改原型上设置的值,而是在实例上创建一个具有新值的新属性,例如:

 var myCar = new Vehicle();
 myCar.wheelCount // === 4

现在你提到的场景 - 设置默认值,并在构造函数中设置实例值 - 没有多大意义,因为你必须使用Object.getPrototypeOf才能达到默认值。这只是一种没有用的可能性,就像所有语言都有很多。