我正在尽力理解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个???这背后的原因是什么?
答案 0 :(得分:2)
bar对象只有一个值为1的p
可以在只读对象中查看值为2的早期p,您可以使用getPrototypeOf访问该对象:
Object.getPrototypeOf(bar).p
您可以看到两者,因为开发人员工具栏旨在打印指定对象的XML表示,该表示应直观地显示所有属性,无论是否可直接访问。
答案 1 :(得分:2)
是。排序。
bar
同时具有:
own的p
属性。
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
内部属性中:
如果您只想在构造函数的原型中拥有实例化对象的数量,可以使用:
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才能达到默认值。这只是一种没有用的可能性,就像所有语言都有很多。