这里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
的原型中。
但是后来当我在对象o
中设置a
的值时,该对象具有新的属性a:7
并且a:5
仍然存在于对象o
的原型中,奇怪的是函数foo()
返回49(7 * 7)而不是25(5 * 5)**,这怎么可能?
编辑:代码在谷歌浏览器的控制台中运行,输出格式是从那里复制的
此行为在规范本身中有很好的文档记录
换句话说,首先检查直接提到的对象 这样的财产;如果该对象包含命名属性,则 引用所指的属性;如果该对象没有 包含命名属性,检查该对象的原型 下一个;等等。
因此,当o
没有自己的a
属性时,会检查其原型是否存在该属性。
但是当a
成为o
的财产时,它被直接捡起,而没有进入它的原型链。
当您尝试访问对象中的属性时,它会尝试在该对象中查找,然后在原型链中查找。因此,通过o.a
进行的基本访问可以访问原型链中的属性a
,直到o
没有自己的属性。
为对象设置原型时,原型属性仅用于读取访问。你可以阅读它们,但是当你尝试改变它的值时,这里的[[Set]]内部属性会完成他的工作。它的工作是当你为不存在的属性(自己的属性,而不是原型链中的那些属性)分配一个值时,它会创建一个值,然后分配给它。因此,在您的情况下,您没有自己的名称为a
的属性,因此它只是创建一个新属性,使其成为o
的所有者并分配给它。原型的属性现在只能通过直接访问prototype
来访问。
在您使用的函数中this
.当你调用o.foo()
时,this
引用的上下文是对象o
,因为它有自己的属性,名称为a
,值7
,所以值7
在其中使用。
o.foo()
表示对象o
调用方法foo
,从那里 这意味着this
实际上是对象o
。
object_o's_property.a*object_o's_property.a
在第一种情况下是 5 * 5。为什么?因为搜索从o
对象开始,并将继续搜索,直到找到它或命null
值(即原型链的末尾)。同样,将从o
开始搜索,然后递归地proto
和proto
,直到找到属性或命中null
。