Javascript ECMAScript 5已定义-用于构造和继承的通用工厂模式,[Object.create()]

Javascript ECMAScript 5已定义-用于构造和继承的通用工厂模式,[Object.create()],javascript,inheritance,Javascript,Inheritance,ECMAScript 5 为构造和继承定义了一个非常常见的工厂模式,称为Object.create()。我只是将对象传递给 继承并重新获取一个新对象,所有这些都已正确连接 考虑一下这个片段: var a = { phrase: "Hello", say: function(){ alert(this.phrase); } }; var b = Object.create(a); 我的理解是否正确,如下所示 第一次创建b时,它有一个原型继承属性,名为 短语,表示属性不在实例上(b

ECMAScript 5 为构造和继承定义了一个非常常见的工厂模式,称为Object.create()。我只是将对象传递给 继承并重新获取一个新对象,所有这些都已正确连接

考虑一下这个片段:

var a = {
    phrase: "Hello",
    say: function(){ alert(this.phrase); }
};
var b = Object.create(a);
我的理解是否正确,如下所示

第一次创建b时,它有一个原型继承属性,名为 短语,表示属性不在实例上(b.短语), 但实际上是在原型上(b.prototype.phrase)。如果我是 读取b.phrase的值时,JavaScript会隐式地 查一下,在原型机上找到,然后还给我

但是,当我将一个新值赋值给b.phrase时,我发现它不会影响继承的 b、 prototype.phrase,但已设置(重写)优先于继承的实例属性b.phrase b、 prototype.phrase用于将来的属性访问。为什么?

b.phrase = "World";
a.say(); // alerts Hello              >> This hasn't changed. Why?
b.say(); // alerts World

这是因为原型链。JavaScript运行时首先查找自己对象的属性,如果没有找到任何内容,则在其原型上查找该属性,依此类推


另一方面,您并没有重写属性,但您只是将一个属性添加到整个对象中,它隐藏了原型的一个属性,而且这种情况再次发生是因为原型链的工作方式。

这种情况发生是因为原型链。JavaScript运行时首先查找自己对象的属性,如果没有找到任何内容,则在其原型上查找该属性,依此类推


另一方面,您并没有重写属性,只是将一个属性添加到整个对象中,它隐藏了原型的一个属性,而且这种情况再次发生,因为原型链是如何工作的。

这是javascript属性查找/分配的工作方式。若要更新prototype属性,可以在prototype对象内创建对象

var proto = {
    fields: {
        phrase: 'Hello'
    },
    say: function () { console.log(this.fields.phrase) }
};

var a = Object.create(proto);

a.fields.phrase = 'World';
proto.say();
a.say();
那么,这里发生了什么

a.fields.phrase='World'
等于

var tmp = a.fields;
tmp.phrase = 'World';
a.fields===a.uuu proto\uuuuu.fields//true

这就是在原型中更新属性的原因

在您的示例中,您只需将值分配给对象,js引擎就会执行您想要的操作—将带有键“短语”的值“World”分配给对象a,这并不奇怪


这是javascript属性查找/分配的工作方式。若要更新prototype属性,可以在prototype对象内创建对象

var proto = {
    fields: {
        phrase: 'Hello'
    },
    say: function () { console.log(this.fields.phrase) }
};

var a = Object.create(proto);

a.fields.phrase = 'World';
proto.say();
a.say();
那么,这里发生了什么

a.fields.phrase='World'
等于

var tmp = a.fields;
tmp.phrase = 'World';
a.fields===a.uuu proto\uuuuu.fields//true

这就是在原型中更新属性的原因

在您的示例中,您只需将值分配给对象,js引擎就会执行您想要的操作—将带有键“短语”的值“World”分配给对象a,这并不奇怪


首先接受这句话

var b = Object.create(a);
此语句创建一个新对象,
newObj
(例如)。现在发生了以下事情:

  • b指向
    newObj

  • newObj通过
    [[prototype]]
    参考链接到a的对象

到目前为止,
newObj
没有任何方法或属性

b.Say()
--
b将指向
newObj
,因此首先它尝试检查
newObj
是否有
Say()
方法,它没有,因此它尝试通过
[[prototype]]
链进行委托。正如newObj的链接指向a的对象一样。它试图检查a的对象中是否存在
Say()
。因此它在那里找到方法并在
newObj的上下文中执行它。
它打印
'Hello'

b.Phrase='world'

在这里,您将
短语
属性指定给
newObj
对象(由“b”指向)。因此,从下一次开始,如果您尝试执行
b.Phrase
,它将不会遍历
[[Prototype]]
链(即到a的对象),而是在
newObj
本身中找到值

Final b.Say()


由于
newObj
没有
Say()
方法,它将遍历
[[prototype]]]
链,找到方法,并在
newObj
的上下文中执行它。由于
newObj
有短语属性,所以
这个短语返回
'world'
首先接受这个语句

var b = Object.create(a);
此语句创建一个新对象,
newObj
(例如)。现在发生了以下事情:

  • b指向
    newObj

  • newObj通过
    [[prototype]]
    参考链接到a的对象

到目前为止,
newObj
没有任何方法或属性

b.Say()
--
b将指向
newObj
,因此首先它尝试检查
newObj
是否有
Say()
方法,它没有,因此它尝试通过
[[prototype]]
链进行委托。正如newObj的链接指向a的对象一样。它试图检查a的对象中是否存在
Say()
。因此它在那里找到方法并在
newObj的上下文中执行它。
它打印
'Hello'

b.Phrase='world'

在这里,您将
短语
属性指定给
newObj
对象(由“b”指向)。因此,从下一次开始,如果您尝试执行
b.Phrase
,它将不会遍历
[[Prototype]]
链(即到a的对象),而是在
newObj
本身中找到值

Final b.Say()

由于
newObj
没有
Say()
方法,它将遍历
[[prototype]]]
链,找到方法,并在
newObj
的上下文中执行它。正如
newObj
具有短语属性,因此
this.phrase