考虑一段代码
function F(){
this.p=10;
}
F.prototype.newProp='some value';
var f1=new F(), f2=new F();
alert(f1.__proto__==f2.__proto__); //returns true. implies f1 and f2 share same instance of prototype object
f1.newProp='new value'; //changing the value of inherited property
alert(f2.newProp); //returns 'some value'
现在问题是f1和f2是否共享相同的[[prototype]]对象实例 而如果 javascript中的属性检索通过沿着原型链行走
因此,如果我更改共享[[prototype]]对象的属性值(在本例中为newProp), 怎么没有反映在f2中, 自f1。 proto == f2。 proto (这意味着它的SAME对象) 那么为什么改变f1的newProp不会改变f2的newProp(都从相同的原型对象继承,没有?)
令人惊讶的是,改变f1。 proto .newProp反映了检索“f1.newProp”时的变化
那么,是f1.newProp和f1。 proto .newProp不同的属性?
我认为该属性在javascript中查找,通过在原型链中连续看起来更高。
我很抱歉,如果我的问题听起来很幼稚,但我无法理解:
如果1)f1。 proto == f2。 proto // true!暗示对象f1和f2引用相同的[[prototype]]对象,它们从中继承
如果
2)在对象中找不到的属性在其原型中被搜索。
那么为什么改变f1.newProp也不会反映在f2.newProp中呢?因为两者都有共同的[[prototype]]属性,如第(1)点所示
原型对象的属性是否被单独复制到f1和f2中。 ? 但那就违反了第(2)条[在对象中找不到时查找原型链的属性]
请解释这里的矛盾。非常感谢你:))
================== EDIT =====
谢谢@ jfriend00的回复。
但我要说我有这段代码
function Person(name, age){
this.name=name;
this.age=age;
alert("obj created:"+name);
}
function Employee(name,age,eid){
this.base=Person;
this.base(name,age);
this.eid=eid;
}
Employee.prototype=new Person;
var ob1=new Employee('name1',23,100);
var ob2=new Employee('name2',24,101);
在这里,显然是ob1。 proto == ob2。 proto 但如果我没有弄错的话,每个员工的实例都有2个对象
1是员工对象本身,只有1个属性eid(和另一个基本功能)
2nd是Person对象,由employee对象的[[prototype]]属性引用。此对象具有名称和年龄属性.. 因此,员工obj实际上从其[[prototype]] Person对象存储和检索名称和年龄。 我是对的吗?
如果是这样,并且因为ob1。 proto == ob2。 proto ,那么我们如何能够存储两个对象的唯一名称和年龄?
我的意思是,这里似乎每个员工都有一个原型对象。 如果你能解释一下,非常感谢你:)
还有一个问题是:
即使注释掉
,上面的代码怎么会起作用Employee.prototype=new Person;
在上面的行中,从而打破了2个objs之间的联系。继承仍然有效,因为我已将Person函数声明为Employee的属性并从中调用Person。 这是怎么回事 谢谢你:))
答案 0 :(得分:1)
原型对象在所有对象之间共享(如您所示)。
但是,当您为属性分配对象时,它不会更改原型,属性会继续对象本身,并且由于解析属性引用的查找顺序,新分配的属性对象本身在原型之前找到,因此它成为活动属性。
当您引用对象上的属性时,会有搜索顺序。首先,它直接在对象上查找属性。如果未找到匹配项,则会搜索原型链。
当您写入对象上的属性时,它永远不会写入原型,除非您显式引用原型对象,而是将属性直接放在对象上,然后该属性成为活动属性(基本上覆盖了什么&#39) ; s在原型上。)
您可以使用.hasOwnProperty()
判断属性是在对象本身上还是在原型上。只有当属性直接在对象上时,才会返回true
。
所以,在你的代码中:
f1.newProp='new value'; //changing the value of inherited property
这会直接向对象添加一个新属性(而不是在原型上),它基本上会覆盖原型上的内容。
通常,数据属性通常在构造函数中设置,以避免对属性可以驻留的两个可能位置产生任何混淆,如果您要写入它们,那么最初确实没有优势在原型上指定它们。函数属性(例如方法)通常在原型中设置,因为它们通常不会被写入,因此只需要一个包含可以从中读取的共享原型对象就更有效。
答案 1 :(得分:1)
设置f1.newProp = 'new value'
后,它不再在原型上设置newProp
,而是在f1
对象本身上设置var f1=new F(), f2=new F();
console.log(f1.hasOwnProperty('newProp')); // returns false, because it is from prototype
f1.newProp = 'new value';
console.log(f1.hasOwnProperty('newProp')); // returns true
。试试这个,你会看到:
{{1}}