繁体   English   中英

数组属性如何在JS对象中工作

[英]How does the array property work in JS object

对于以下代码,为什么myObjpropB更新? 为什么test.childObj没有自己的属性propB

 var myObj = { propA: '', propB: [] } var fatherObj = { childObj: null, init: function() { this.childObj = Object.create(myObj); this.childObj.propA = 'A'; this.childObj.propB.push(2); } } var test = Object.create(fatherObj); test.init(); console.log(myObj.propB.length); console.log(test.childObj.hasOwnProperty('propA')); console.log(test.childObj.hasOwnProperty('propB')); 

使用Object.create不复制对象,但是创建了一个继承传递的对象的新对象:

  this.childObj { } ->  myObj { propA: "", propB: [] }

现在当你得到一个属性时,它会在继承链中被查找。 因为它无法在子对象中找到,所以它会在myObj查找。 这通常不是问题,因为设置对象属性直接将其设置在对象本身而不使用继承链,因此:

  this.childObj.propA += "test";

myObj上查找propA但在propA上设置childObj 但是,对于引用类型,您不会重写属性,因此:

  this.childObj.propB.push(1);

myObj查找propB ,并推送到那个,结果是:

 this.childObj { propA: "test" } ->  myObj { propA: "", propB: [1] }

要解决这个问题,childObj必须有自己的propB数组:

 this.childObj.propB = this.childObj.propB.slice();

这导致:

 this.childObj { propA: "test", propB: [1] } ->  myObj { propA: "", propB: [1] }

现在推到propB推到在阵列childObj

这是因为myObj成为新创建的test对象的原型(通过Object.create创建它)。

由于你刚刚修改底层支柱propBchildObj (而不是像指派为新值propA ),你只修改原型的道具。 请阅读有关javascript 继承的更多信息。

通过使用Object.create(myObj); myObj成为childObj的原型。 如果在对象中找不到属性并且在原型中找到该属性,则使用原型中的属性。 另请注意, hasOwnProperty告诉对象是否拥有属性本身,如果它仅存在于原型中而不存在于对象中,则返回false。 通过直接在对象上分配属性,可以在对象上设置它,而不是在原型上,但是当您使用push修改属性propB时,不会直接在childObject中找到该属性,因此您可以修改原型。

你必须要小心,因为以这种方式创建的所有对象将共享相同的原型对象,并且通过修改一个,您将为所有实例修改它。

你还要格外小心,因为在javascript中知道你的属性来自原型链的位置可能很棘手,因为myObj也有原型。

 var myObj = { propA: '', propB: [] } var fatherObj = { childObj: null, init: function() { this.childObj = Object.create(myObj); this.childObj.propA = 'A'; this.childObj.propB.push(2); } } var test = Object.create(fatherObj); test.init(); console.log('test: ', test); console.log('test prototype: ', test.__proto__); console.log('test.childObj: ', test.childObj); console.log('test.childObj prototype: ', test.childObj.__proto__); console.log(test.childObj.hasOwnProperty('propA')); console.log(test.childObj.hasOwnProperty('propB')); 

Javascript继承不像大多数其他语言那样工作。 当使用var x = Object.create(someObj) ,新对象x实际上是空的(它没有自己的属性)以及对其原型的引用:单独的对象someObj

您尝试从x访问的任何属性函数都将在someObj查找 - 或者甚至更高,如果someObj也有原型对象等。

当继承的属性是可修改的对象时 ,事情会变得混乱,如在您的示例中。 正如我们所看到的,尝试通过x.propB推送项来修改数组x.propB ,实际上将修改someObj包含的继承数组。

我坚信在原型对象中拥有可修改的对象(包括数组和常规对象)是不好的方式 相反,原型对象应该包含函数 而不包含数据 ,或者至少不包含不可修改的简单字符串,数字和布尔值之外的数据。

总结一下:

  • 函数对于继承很有用,它们不可修改(您无法更改函数体),并且如果需要仍可以覆盖/替换。
  • 数据成为所有继承者的共享数据,除非/直到它们通过重新分配覆盖它,这本身就是一种负担。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM