新的vs对象创建给出不同的结果OO javascript

时间:2014-01-06 00:09:35

标签: javascript oop constructor object-literal

我正在使用一个数据对象点亮,然后尝试创建一个新对象,该对象仅为该实例更改data属性中的属性,这里是来自jsbin的一些测试代码

data = {
  innerData : 1 
}

-------------

'This works :-)'

construct = function(d){
  this.data = Object.create(d);
};

construct.prototype.c = function(n){
  this.data.innerData  =  n;
};

construct.prototype.d = function(){
   console.log(this.data.innerData)
};

--------------

'This does not :-{'

construct = {
  data : Object.create(data),
  changeData : function(n){
    this.data.innerData  =  n;
  },
  showData:function(){
    console.log(this.data.innerData)
  }
}

--------------

newInst = Object.create(construct);
newInst.changeData(5);
newInst.showData();

newInst2 = Object.create(construct);
newInst2showData();

当我使用构造函数/原型函数运行它时它工作,控制台输出5,2

当我使用对象文字运行它时,控制台输出5,5我想当我创建第一个实例时,它会更改实际数据对象而不是构造对象实例的数据属性。

如果有人能够深入解释为什么会发生这种情况会有很大帮助,因为我没有长时间与OOJS合作

更新

所以我有点想把我觉得有用的东西从答案中合并而且我想出了这个....

data = {
  innerData : 1 
}

function construct(d){
  return {
    data : Object.create(d),
    changeData : function(n){
      this.data.innerData  =  n;
    },
    showData : function(){
      console.log(this.data.innerData)
    }
  }
}

build = function(){
 return(new construct(data));
}

newInst = build();
newInst.changeData(5);
newInst.showData();

newInst2 = build();
newInst2.showData();

4 个答案:

答案 0 :(得分:2)

鉴于我们对继承的了解,以下实际做了什么

this.data.innerData  =  n;

其中thisObject.create(construct)的结果?

  1. this没有自己的属性data,因此请查看继承的属性。
  2. 好的,我们找到了data === Object.getPrototypeOf(this).data,称之为d
  3. 接下来将innerData的{​​{1}}设置为d
  4. 那么实际结果是什么?{<1}}属性已经在 prototype 的引用上设置,而不是新的 Object 。 / p>

    为什么会这样?因为如果您有n并尝试执行innerData,则会得到o = {},因此不会抛出错误,它必须访问已定义的对象< / em>的

    o.foo.bar

答案 1 :(得分:1)

第二段代码工作正常:

construct.changeData(2);
construct.showData(); // 2

唯一的区别是,在上面的示例中,construct不是构造函数,因此与第一种方法相比,只有construct.data的单个实例;在其上调用Object.create()将创建一个新对象,但将保留与第一个相同的.data引用。

答案 2 :(得分:1)

在第二个示例中,只有一个data对象。该对象位于construct内,可用于原型链上的所有后续对象。

在第一个示例中,每次创建新实例时都会创建一个新的data对象。因此每个对象都有自己的data副本。

试试这个,第一个例子:

console.log(newInst.data === newInst2.data); // should be false

和第二个例子:

console.log(newInst.data === newInst2.data); // should be true

答案 3 :(得分:1)

这看起来像是尝试创建工厂函数而不是构造函数。由于Object.create现在已经普及,并且可以在不可用的情况下用于这些目的,这可能是最好的默认值,尽管仍然有很多构造函数。

其他一些答案解释了您的尝试出了什么问题。这是你如何做到这一点,以便它按预期工作:

var factory = (function() {
  var clone = function(obj) {return JSON.parse(JSON.stringify(obj));};
  var data = {
    innerData : 1 
  };

  var proto = {
    changeData : function(n){
      this.data.innerData = n;
    },
    showData:function(){
      console.log(this.data.innerData)
    }
  };

  return function() {
    var obj = Object.create(proto);
    obj.data = clone(data);
    return obj;
  }
}());

但看起来你的innerData可能是尝试让这些事情发挥作用的实验。它没有必要,这将更清洁:

var factory = (function() {
  var proto = {
    data: 1,
    changeData : function(n){
      this.data = n;
    },
    showData:function(){
      console.log(this.data)
    }
  };

  return function() {
    return Object.create(proto);
  }
}());