【问题标题】:Javascript module pattern - Object.createJavascript 模块模式 - Object.create
【发布时间】:2015-03-01 22:49:25
【问题描述】:

对于这里到底发生了什么有点困惑。

鉴于这个简单的代码:

stuff = (function(){
    function extendFoo(bar)
    {
        $.extend(this.foo,bar);
    }
    this.foo = {};

    return { foo : foo, extendFoo: extendFoo};
})();

按照这个简单的操作:

zz = Object.create(stuff);
zz.extendFoo({bar:'bar'});
vv = Object.create(stuff); //foo is still extended(??)

所以据我了解,对返回的对象形式 Object.create 进行的操作仍然会影响该对象的原型,因此当您创建一个新对象时,他的原型会发生变化,从而产生一个“修改”版本。

这在很多层面上似乎都是错误的,谁能解释这里发生了什么?

使用以下模式无法重现此行为:

stuff = (function(){

    function setFoo(bar)
    {
        this.foo = bar;
    }
    var foo;

    return { foo : foo, setFoo: setFoo};

})();

所以我怀疑 $.extend 应该归咎于此。

任何输入都会很棒!

【问题讨论】:

  • 请注意,IEFE 中的this.foo = {}; 创建了一个您不想要的全局变量,请使用var foo = {}。不过,这对您的问题没有影响。
  • Prototypal inheritance - Issues with nested objects 是否充分回答了您的问题?您使用模块模式和 setter 方法可能会掩盖问题
  • 您的代码中有两个主要错误:return { foo: foo, 中的foo 未定义,this.foo = {} 中的this 实际上是window 对象。请更正这些

标签: javascript module-pattern revealing-module-pattern


【解决方案1】:

这个问题与模块模式无关,与原型有关。

zz = Object.create(stuff) 

创建一个以stuff 为原型的新对象。

vv = Object.create(stuff) 

使用与原型相同的stuff 对象创建一个新对象。

zzvv 共享同一个原型对象,因此如果您修改原型对象stuff,那么更改将反映在派生对象zzvv 中。无论您是通过$.extend 还是其他方式修改原型都没有关系,无论您是通过派生对象还是原型来修改原型。

在您的代码中,foo 对象附加到原型,而不是派生对象 zzvv。在派生对象zz 上调用extendFoo 时,它正在修改原型上的foo,因此对foo 的更改由派生对象共享。

在你的第二个例子中,setFoo

this.foo = bar;

发生的事情是您在派生对象上设置了foo 属性,所以现在它覆盖了原型的foo。在派生对象上运行setFoo 后,该对象的foo 不再是原型的foo。你可以通过运行看到这一点

zz = Object.create(stuff);
console.log(zz.hasOwnProperty('foo')); // false
zz.setFoo(bar);
console.log(zz.hasOwnProperty('foo')); // true
delete zz.foo;
console.print(zz.foo); // foo is the original foo, not null
console.log(zz.hasOwnProperty('foo')); // false

您实际上会取回原来的 foo 而不是 null

setFoo 在第二种情况下起作用的原因是因为您不再修改原型,因此这些更改不再在派生对象之间共享。与原作的

$.extend(this.foo,bar);

您正在就地修改对象this.foo 而不是覆盖。你也可以通过hasOwnProperty看到这个

zz = Object.create(stuff);
console.log(zz.hasOwnProperty('foo')); // false
zz.extendFoo({bar:'bar'});
console.log(zz.hasOwnProperty('foo')); // false

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 2012-04-25
    • 2011-07-02
    • 2012-12-19
    • 2012-12-09
    • 1970-01-01
    • 2014-05-19
    相关资源
    最近更新 更多