0

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

例如

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

每当任何一个sportScratchpads 中的值发生变化时,它都会在profileScratchpadOne和中发生变化profileScratchpadTwo

我认为正在传递一个参考。

我研究了扩展运算符、原型、构造函数,但还没有找到一种防弹、简洁的方法。

解决这个问题的最简洁的方法是什么,并且每次都传递一个新的对象?

4

3 回答 3

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();

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

于 2017-02-12T20:39:22.650 回答
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);
于 2017-02-12T20:27:44.217 回答
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)

于 2017-02-12T20:32:54.727 回答