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

时间:2015-12-27 12:25:12

标签: javascript inheritance

ECMAScript 5 已经为构造和继承定义了一个非常常见的工厂模式,称为Object.create()。我只是将对象传递给 继承并回来一个新对象都正确连线。

考虑一下代码段:

var a = {
    phrase: "Hello",
    say: function(){ alert(this.phrase); }
};
var b = Object.create(a);

我的理解是否正确如下所示?

  

首次创建b时,它具有一个名为的原型继承属性   短语,意味着该属性不在实例上(b.phrase),   但实际上是在原型上(b.prototype.phrase)。如果我去的话   在那时读取b.phrase的值,JavaScript会隐式地   查一查,在原型上找到它,然后把它还给我。

b.say(); // alerts Hello

但是,当我为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

3 个答案:

答案 0 :(得分:3)

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

另一方面,你不是覆盖一个属性,但你只是在整个对象中添加一个,它隐藏原型'一个又一个,这是因为原型链的工作原理。

答案 1 :(得分:2)

这是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.__proto__.fields // true

这就是为什么在原型中更新了属性。

在你的例子中,你只需为对象分配值,js引擎就可以做你想要的 - 用对象“短语”给对象分配值“World”,没什么奇怪的

More info about how objects work in js

答案 2 :(得分:0)

首先采取此声明

var b = Object.create(a);

此语句创建一个新对象newObj(例如)。现在发生以下事情:

  • b指向newObj

  • newObj通过[[prototype]]引用链接到对象。

直到现在newObj没有任何方法或属性。

选择b.Say() - b将指向newObj,因此首先它会尝试检查newObj是否有Say()方法,它不会因此它试图通过[[prototype]]链委托。由于newObj's [[prototype]]链接指向某个对象。它试图检查对象中是否存在Say()。因此,它找到了那里的方法&使用newObj.的上下文执行它打印'Hello'

b.Phrase='world'
在这里,您要将phrase属性分配给newObj对象(由' b'指向)。因此,从下次开始,如果您尝试执行b.Phrase,它将不会遍历[[Prototype]]链(即对象的对象),而是会在newObj中找到值本身。

Final b.Say()
由于newObj没有Say()方法,它会遍历[[prototype]]链,找到方法,&在newObj的上下文中执行它。由于newObj具有词组属性,因此this.phrase会返回'world'