2017-02-12 4 views
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 

Всякий раз, когда значение либо sportScratchpad с получает изменен, он делает в обоих profileScratchpadOne и profileScratchpadTwo.

Я считаю, что ссылка передается.

Я исследовал спред оператора, прототипы, конструкторы и еще не нашел пуленепробиваемый, сжатый подход.

Что является самым кратким способом обойти это и каждый раз передавать новый объект?

+0

Если достаточно мелкой копии (как для примера, за исключением, возможно, для свойства лиг - в зависимости от ваших ожиданий), тогда '= Object.assign ({}, sportPrototype);' – trincot

ответ

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.create и Object.assign будет иметь проблему с свойством leagues, потому что он является ссылочным типом и поэтому будет использоваться между всеми копиями, если вы его мутируете (путем добавления элементов и т. д.). По этой причине вам понадобится создать новый пустой массив для leagues (и любых других свойств ссылочного типа), если вы хотите скопировать прототип.

Вы могли бы позаботиться об этом с помощью функции фабрики, как:

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

    return newObj; 
} 

profileScratchpadOne.sportScratchpad = sportDefaults() 

Edit: Преимущество 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)

+0

Спасибо за лучшую адресацию прецедент. Что-то вроде Array.create? – softcode

+1

@softcode Вы можете просто использовать пустой массив: 'profileScratchpadOne.sportScrachpad.leagues = []'. – JLRishe

+1

@softcode Добавлено добавление с дополнительным подходом, который вы могли бы использовать. – JLRishe

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

Хотя 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(); 

Теперь последние два задания будут производить объекты, которые полностью независимы.

+0

Извините, что вы удалили прием из моего ответа. Была ли проблема? – trincot