用空原型

时间:2017-02-12 20:23:55

标签: javascript ecmascript-6 spread-syntax

我试图通过将一个数据完全替换为具有一组具有空值的键的对象来刷新一些数据。

e.g。

const sportPrototype = {
  name: '',
  players: '',
  displacement: '',
  points: '',
  leagues: []
}

var profileScratchpadOne = {
  sportScratchpad: {
    name: 'Soccer',
    players: '16',
    displacement: 'Foot',
    points: 'unlimited',
    leagues: ["Fifa"]
  }
}

profileScratchpadOne.sportScratchpad = sportPrototype
profileScratchpadTwo.sportScratchpad = sportPrototype

每当sportScratchpad中的值发生变化时,profileScratchpadOneprofileScratchpadTwo都会发生变化。

我认为正在传递参考。

我调查了传播操作符,原型,构造函数,还没有找到一种防弹,简洁的方法。

最简洁的解决方法是什么,每次都传递一个新鲜的物体?

3 个答案:

答案 0 :(得分:2)

虽然此处Object.assign可以使用,但对象仍然会共享相同的leagues数组。只有原始类型的属性才能独立生活。您可以找到执行深层复制的函数,但我认为在这种情况下您可以使用构造函数模式:

function SportPrototype() {
  this.name = '';
  this.players = '';
  this.displacement = '';
  this.points = '';
  this.leagues = [];
}

var profileScratchpadOne = {};
var profileScratchpadTwo = {};

var o = new SportPrototype();
o.name = 'Soccer';
o.players = '16';
o.displacement = 'Foot';
o.points = 'unlimited';
o.leagues = ["Fifa"];
profileScratchpadOne.sportScratchpad = o;

profileScratchpadOne.sportScratchpad = new SportPrototype();
profileScratchpadTwo.sportScratchpad = new SportPrototype();

现在最后两个分配将产生完全独立的对象。

答案 1 :(得分:1)

编辑:由于sportPrototype上至少有一个对象(数组),因此浅拷贝不是正确的选择。可以选择最简单的深层复制:

function deepCopy(o) {
  return JSON.parse(JSON.stringify(o));
}

const sportPrototype = {
  name: '',
  players: '',
  displacement: '',
  points: '',
  leagues: []
}

var profileScratchpadOne = {
  sportScratchpad: {
    name: 'Soccer',
    players: '16',
    displacement: 'Foot',
    points: 'unlimited',
    leagues: ["Fifa"]
  }
}

profileScratchpadOne.sportScratchpad = deepCopy(sportPrototype);
profileScratchpadTwo.sportScratchpad = deepCopy(sportPrototype);

答案 2 :(得分:1)

正如其他人所提到的,Object.assign()是创建对象浅层副本的一种方法。另一种选择是使用Object.create(),其中"包装"对象,以便为新对象的属性赋值不会覆盖原型的属性:



const sportPrototype = {
  name: '',
  players: '',
  displacement: '',
  points: '',
  leagues: []
}

var profileScratchpadOne = {
  sportScratchpad: {
    name: 'Soccer',
    players: '16',
    displacement: 'Foot',
    points: 'unlimited',
    leagues: ["Fifa"]
  }
}

var profileScratchpadTwo = {}

profileScratchpadOne.sportScratchpad = Object.create(sportPrototype)
profileScratchpadTwo.sportScratchpad = Object.create(sportPrototype)

console.log(sportPrototype.name);
console.log(profileScratchpadOne.sportScratchpad.name);
console.log(profileScratchpadTwo.sportScratchpad.name);

profileScratchpadOne.sportScratchpad.name = 'Jai Alai'
profileScratchpadTwo.sportScratchpad.name = 'Curling'

console.log(sportPrototype.name);
console.log(profileScratchpadOne.sportScratchpad.name);
console.log(profileScratchpadTwo.sportScratchpad.name);




但是,Object.createObject.assign都会导致leagues属性出现问题,因为它是一种引用类型,因此如果您将其变异,则会在所有副本之间共享(通过添加元素等)。因此,当您想要复制原型时,您基本上需要为leagues(以及任何其他引用类型属性)创建一个新的空数组。

您可以使用工厂功能处理此问题,例如:

function sportDefaults() {
    var newObj = Object.create(sportPrototype);
    newObj.leagues = [];

    return newObj;
}

profileScratchpadOne.sportScratchpad = sportDefaults()

编辑 Object.create的好处是原始原型只有一个副本,并根据需要创建新属性,从而节省了内存。如果您不是所有关心内存的问题,您可以创建一个函数,每次都返回原型的全新副本。这将回避上述问题与参考类型:



function sportDefaults() {
  return {
    name: '',
    players: '',
    displacement: '',
    points: '',
    leagues: []
  }
}

var profileScratchpadOne = {}
var profileScratchpadTwo = {}

profileScratchpadOne.sportScratchpad = sportDefaults()
profileScratchpadTwo.sportScratchpad = sportDefaults()

console.log('- before assignment')
console.log(profileScratchpadOne.sportScratchpad.name)
console.log(profileScratchpadTwo.sportScratchpad.name)

profileScratchpadOne.sportScratchpad.name = 'Jai Alai'
profileScratchpadTwo.sportScratchpad.name = 'Curling'

console.log('- after assignment')
console.log(profileScratchpadOne.sportScratchpad.name)
console.log(profileScratchpadTwo.sportScratchpad.name)