【问题标题】:javascript: how exactly are properties inherited from prototype?javascript:如何从原型继承属性?
【发布时间】:2015-01-17 22:24:38
【问题描述】:

考虑一段代码

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 //真!意味着对象 f1 和 f2 都引用了它们所继承的同一个 [[prototype]] 对象

如果

2) 在其原型中搜索对象中未找到的属性。

那么为什么改变 f1.newProp 并没有反映在 f2.newProp 中呢?因为两者都有共同的 [[prototype]] 属性,如第 (1) 点所示

原型对象的属性是否被单独复制到 f1 和 f2 中。 ? 但这违反了第(2)点[在对象中找不到时查找原型链的属性]

请解释这里的矛盾。非常感谢你:)

===================编辑================

感谢@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(和其他一个基本 func)

2nd 是员工对象的 [[prototype]] 属性引用的 Person 对象。该对象具有名称和年龄属性.. 因此,employee obj 实际上从其 [[prototype]] Person 对象中存储和检索姓名和年龄。 我说的对吗?

如果是这样,并且由于 ob1.proto==ob2.proto,那么我们如何能够存储两个对象的唯一名称和年龄?

我的意思是,这里似乎每个员工都有一个原型对象。 如果你能解释一下,非常感谢你:)

还有一个查询是:

为什么上面的代码即使注释掉也能工作

Employee.prototype=new Person;

在上面的行中,从而破坏了 2 个对象之间的链接。继承仍然有效,因为我已将 Person 函数声明为 Employee 的属性并从中调用 Person 。 这是如何工作的 谢谢你:)

【问题讨论】:

  • 在您的附加代码中,您需要从派生对象构造函数调用基础对象构造函数,以便它可以对新创建的对象Person.call(this, name, age); 进行适当的初始化工作。我不知道你正在学习什么参考形式,但是任何关于 Javascript 继承的好的参考都应该向你展示这一点,所以它可能在你使用的任何参考中。
  • 好的,但是你能解释一下我对编辑部分的原始问题吗? ob1 和 ob2 是如何共享同一个原型对象但又具有不同的 name 和 age 属性的,这些属性本身存储在原型对象中。谢谢
  • 那是哪个问题?你问了很多问题,我不知道你还需要帮助哪一个。仅当您实际在其上使用任何东西时才需要原型。如果你不使用它,那么你不必设置它,因为它没有任何东西。
  • 我在我编辑的部分讨论了代码 sn-p。 ob1 和 ob2 具有相同的原型对象。原型对象存储“姓名”和“年龄”属性,对吧?如果 ob1 和 ob2 的原型对象相同,那么 ob1 和 ob2 如何能够在 2 个不同的对象中存储唯一的“姓名”和“年龄”?我希望你能理解我的问题。谢谢
  • 最好不要创建Parent的实例来设置为Child的原型。原型属性如何使用、设置、变异和隐藏以及如何继承在此处详细说明:stackoverflow.com/questions/16063394/…

标签: javascript inheritance


【解决方案1】:

原型对象在所有对象之间共享(如您所示)。

但是,当您将属性分配给对象时,它不会更改原型,属性会继续存在于对象本身上,并且由于解析属性引用的查找顺序,新分配的属性会出现在对象本身上在原型上的那个之前找到,因此它成为活动属性。

当您引用对象的属性时,会有一个搜索顺序。首先,它直接在对象上查找属性。如果未找到匹配项,则搜索原型链。

当您写入对象上的属性时,除非您明确引用原型对象,否则它永远不会写入原型,而是直接在对象上放置一个属性,然后该属性成为活动属性(基本上覆盖了原型)。

您可以使用.hasOwnProperty() 判断属性是在对象本身上还是在原型上。只有当属性直接在对象上时才会返回true

所以,在你的代码中:

f1.newProp='new value'; //changing the value of inherited property

这会直接向对象(而不是原型)添加一个新属性,它实际上会覆盖原型上的内容。


一般来说,数据属性通常在构造函数中设置,以避免混淆属性可以驻留的两个可能位置,如果您正在写入它们,那么最初在原型上指定它们确实没有任何优势。函数属性(例如方法)通常在原型中设置,因为它们通常不会被写入,因此只拥有一个包含可读取它们的共享原型对象会更有效。

【讨论】:

  • 非常感谢。但可以说我有这个代码code function Person(name, age){ this.name=name;这个.age=年龄; alert("obj 创建:"+name); } function Employee(name,age,eid){ this.base=Person; this.base(姓名,年龄);这个.eid=eid; } Employee.prototype=新人; var ob1=new Employee('name1',23,100); var ob2=new Employee('name2',24,101); code // ob1.__proto__ == ob2.__proto__ 是真的
  • @Sarabjeet - 多行代码在 cmets 中不可读。您可以使用原始帖子上的编辑链接将您所询问的内容放在那里,然后发表评论以引起对新代码的关注。
  • @Sarabjeet - 你用你的附加代码编辑你自己的帖子,而不是我的。
  • 对不起 jfriend00,我是这个网站的新手。我已经编辑了我的帖子。
【解决方案2】:

一旦你设置了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

【讨论】:

    猜你喜欢
    • 2023-03-16
    • 2016-02-15
    • 2013-03-05
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多