当稍后再次设置派生对象的属性时,从基础对象继承的属性会发生什么?

时间:2018-03-05 09:19:38

标签: javascript inheritance prototype javascript-objects

此处 Object.create()用于继承。

JavaScript代码:



var x = {
  a: 5, 
  foo: function() {
    return this.a * this.a;
  }
};

var o = Object.create(x);

console.log('\'x\':', x);
console.log('Object \'o\':', o);
console.log('Property \'o.a\':', o.a);
console.log('Method \'o.foo()\':', o.foo());

o.a = 7;
console.log('-----After setting o.a directly-----');

console.log('Object \'o\':', o);
console.log('Property \'o.a\':', o.a);
console.log('Method \'o.foo()\':', o.foo());




上述代码的输出为:

'x': { a: 5, foo: [Function: foo] }
Object 'o': {}
              __proto__: 
                  a: 5
                  foo: ƒ ()
                  __proto__: Object

Property 'o.a': 5
Method 'o.foo()': 25

-----After setting o.a directly-----

Object 'o': {a: 7}
              a: 7
              __proto__: 
                a: 5
                foo: ƒ ()
                __proto__: Object

Property 'o.a': 7
Method 'o.foo()': 49

因此,第一个值a和函数foo()x对象派生到o个对象,因此它们位于对象o的原型中。

但稍后当我在对象a中设置o的值时,该对象有一个新属性a:7以及a:5仍然存在于对象原型中o奇怪的是函数foo()返回49(7 * 7)而不是25(5 * 5)**,这怎么可能?

编辑代码在Google Chrome控制台中运行,输出格式从那里复制

3 个答案:

答案 0 :(得分:1)

当您尝试访问对象中的属性时,它会尝试在该对象中查找,然后在原型链中查找。因此,通过o.a进行基本访问可以访问原型链中的属性a,直到o没有它为止。

为对象设置原型时,原型属性仅用于 读取访问 。您可以阅读它们,但是当您尝试更改它的值时,此处 [[Set]] 内部属性可以完成其工作。它的工作是当你为一个不存在的属性(自己的属性,而不是那些在原型链中的属性)赋值时,它创建一个然后分配给它。因此,在您的情况下,您没有名称为a的自有属性,因此它只创建一个新属性,使其为o拥有并分配给它。现在,只有直接访问prototype

,才能访问原型的属性

在您使用this的功能中。当您致电o.foo()时,this引用的上下文是对象o,因为它有一个名为a且值为7的自有属性,在其中使用了值7

答案 1 :(得分:1)

o.foo()表示对象o从那里调用方法foo  这意味着this实际上是对象o

object_o's_property.a*object_o's_property.a在第一种情况下是5 * 5.为什么?因为搜索从o对象开始,并将继续搜索,直到找到它或命中null值,即原型链的末尾。再次,将从o然后以proto及其proto递归开始搜索,直到找到属性或点击null

答案 2 :(得分:1)

spec本身

中详细记录了此行为
  

换句话说,首先检查直接提到的对象   这样的财产;如果该对象包含命名属性,即   引用所指的财产; 如果该对象没有   包含命名属性,检查该对象的原型   下一个;等等

所以,o没有自己的a属性时,检查其原型是否存在属性。

a成为o 的自有属性时,直接获取它而不进入其原型链