Можно ли разрушить существующий объект? (Javascript ES6)
Например, если у меня есть два объекта:
var foo = {
x: "bar",
y: "baz"
}
и
var oof = {}
и я хотел передать значения x и y из foo в oof. Есть ли способ сделать это, используя синтаксис деструктурирования es6?
возможно что-то вроде:
oof{x,y} = foo
Ответы
Ответ 1
Хотя уродливый и немного повторяющийся, вы можете сделать
({x: oof.x, y: oof.y} = foo);
который прочитает два значения объекта foo
и запишет их в соответствующих местах объекта oof
.
Лично я бы все же лучше прочитал
oof.x = foo.x;
oof.y = foo.y;
или же
['x', 'y'].forEach(prop => oof[prop] = foo[prop]);
хоть.
Ответ 2
Нет, деструктурирование не поддерживает выражения членов в сокращенных выражениях, но только простые имена свойств в текущее время. Там были разговоры об этом на esdiscuss, но никаких предложений не поступит в ES6.
Возможно, вы можете использовать Object.assign
- если вам не нужны все собственные свойства, вы все равно можете сделать
var foo = …,
oof = {};
{
let {x, y} = foo;
Object.assign(oof, {x, y})
}
Ответ 3
IMO - это самый простой способ выполнить то, что вы ищете:
let { prop1, prop2, prop3 } = someObject;
let data = { prop1, prop2, prop3 };
// data === { prop1: someObject.prop1, ... }
В принципе, разрушитесь в переменных, а затем используйте сокращенное значение инициализатора, чтобы создать новый объект. Нет необходимости в Object.assign
Я думаю, что это самый читаемый способ, так или иначе. Здесь вы можете выбрать точные реквизиты из someObject
, которые вы хотите. Если у вас есть существующий объект, вы просто хотите объединить реквизиты, сделайте что-то вроде этого:
let { prop1, prop2, prop3 } = someObject;
let data = Object.assign(otherObject, { prop1, prop2, prop3 });
// Makes a new copy, or...
Object.assign(otherObject, { prop1, prop2, prop3 });
// Merges into otherObject
Другой, возможно, более чистый способ записи:
let { prop1, prop2, prop3 } = someObject;
let newObject = { prop1, prop2, prop3 };
// Merges your selected props into otherObject
Object.assign(otherObject, newObject);
Я использую это для POST
запросов, где мне нужно всего лишь несколько частей дискретных данных. Но я согласен, что для этого должен быть один лайнер.
Ответ 4
Помимо Object.assign
существует синтаксис распространения объектов, который является предложением Stage 2 для ECMAScript.
var foo = {
x: "bar",
y: "baz"
}
var oof = { z: "z" }
oof = {...oof, ...foo }
console.log(oof)
/* result
{
"x": "bar",
"y": "baz",
"z": "z"
}
*/
Но для использования этой функции вам нужно использовать плагин stage-2
или transform-object-rest-spread
для babel. Вот демон на babel с stage-2
Ответ 5
Плагин BabelJS
Если вы используете BabelJS, теперь вы можете активировать мой плагин babel-plugin-transform-object-from-destructuring
(см. Пакет npm для установки и использования).
У меня была та же проблема, описанная в этой теме, и для меня она была очень утомительной, когда вы создаете объект из выражения деструктурирования, особенно когда вам нужно переименовать, добавить или удалить свойство. С этим плагином поддержка таких сценариев становится намного проще для вас.
Пример объекта
let myObject = {
test1: "stringTest1",
test2: "stringTest2",
test3: "stringTest3"
};
let { test1, test3 } = myObject,
myTest = { test1, test3 };
можно записать как:
let myTest = { test1, test3 } = myObject;
Пример массива
let myArray = ["stringTest1", "stringTest2", "stringTest3"];
let [ test1, , test3 ] = myArray,
myTest = [ test1, test3 ];
можно записать как:
let myTest = [ test1, , test3 ] = myArray;
Ответ 6
Это вполне возможно. Просто не в одном утверждении.
var foo = {
x: "bar",
y: "baz"
};
var oof = {};
({x: oof.x, y: oof.y} = foo); // {x: "bar", y: "baz"}
(Обратите внимание на круглые скобки вокруг утверждения.) Но имейте в виду, что удобочитаемость важнее, чем игра в код :).
Источник: http://exploringjs.com/es6/ch_destructuring.html#sec_assignment-targets
Ответ 7
Вы можете вернуть разрушенный объект в функцию стрелки и использовать Object.assign(), чтобы присвоить его переменной.
const foo = {
x: "bar",
y: "baz"
}
const oof = Object.assign({}, () => ({ x, y } = foo));
Ответ 8
Вы можете просто использовать реструктуризацию для этого:
const foo = {x:"a", y:"b"};
const {...oof} = foo; // {x:"a", y:"b"}
Или объедините оба объекта, если oof имеет значения:
const foo = {x:"a", y:"b"};
let oof = {z:"c"}
oof = Object.assign({}, oof, foo)
Ответ 9
DRY
var a = {a1:1, a2: 2, a3: 3};
var b = {b1:1, b2: 2, b3: 3};
const newVar = (() => ({a1, a2, b1, b2})).bind({...a, ...b});
const val = newVar();
console.log({...val});
// print: Object { a1: 1, a2: 2, b1: 1, b2: 2 }
или же
console.log({...(() => ({a1, a2, b1, b2})).bind({...a, ...b})()});
Ответ 10
Это работает в chrome 53.0.2785.89
let foo = {
x: "bar",
y: "baz"
};
let oof = {x, y} = foo;
console.log(`oof: ${JSON.stringify(oof)});
//prints
oof: {
"x": "bar",
"y": "baz"
}
Ответ 11
Я придумал этот метод:
exports.pick = function pick(src, props, dest={}) {
return Object.keys(props).reduce((d,p) => {
if(typeof props[p] === 'string') {
d[props[p]] = src[p];
} else if(props[p]) {
d[p] = src[p];
}
return d;
},dest);
};
Что вы можете использовать следующим образом:
let cbEvents = util.pick(this.props.events, {onFocus:1,onBlur:1,onCheck:'onChange'});
let wrapEvents = util.pick(this.props.events, {onMouseEnter:1,onMouseLeave:1});
i.e, вы можете выбрать, какие свойства вы хотите, и поместить их в новый объект. В отличие от _.pick
вы также можете переименовать их в одно и то же время.
Если вы хотите скопировать реквизиты на существующий объект, просто установите параметр dest
.
Ответ 12
Это своего рода обман, но вы можете сделать что-то вроде этого...
const originalObject = {
hello: 'nurse',
meaningOfLife: 42,
your: 'mom',
};
const partialObject = (({ hello, your }) => {
return { hello, your };
})(originalObject);
console.log(partialObject); // { hello: 'nurse', your: 'mom' }
На практике, я думаю, вы редко хотели бы использовать это. Следующее намного яснее... но не так весело.
const partialObject = {
hello: originalObject.hello,
your: originalObject.your,
};
Другой совершенно другой маршрут, который включает в себя прошивку с прототипом (осторожно сейчас...):
if (!Object.prototype.pluck) {
Object.prototype.pluck = function(...props) {
return props.reduce((destObj, prop) => {
destObj[prop] = this[prop];
return destObj;
}, {});
}
}
const originalObject = {
hello: 'nurse',
meaningOfLife: 42,
your: 'mom',
};
const partialObject2 = originalObject.pluck('hello', 'your');
console.log(partialObject2); // { hello: 'nurse', your: 'mom' }
Ответ 13
Это наиболее читаемое и кратчайшее решение, которое я мог бы предложить:
let props = {
isValidDate: 'yes',
badProp: 'no!',
};
let { isValidDate } = props;
let newProps = { isValidDate };
console.log(newProps);
Он выведет { isValidDate: 'yes' }
Было бы неплохо когда-нибудь сказать что-то вроде let newProps = ({ isValidDate } = props)
, но, к сожалению, это не то, что поддерживает ES6.
Ответ 14
Это не красивый способ, и я не рекомендую его, но это возможно, просто для знаний.
const myObject = {
name: 'foo',
surname: 'bar',
year: 2018
};
const newObject = ['name', 'surname'].reduce(
(prev, curr) => (prev[curr] = myObject[curr], prev),
{},
);
console.log(JSON.stringify(newObject)); // {"name":"foo","surname":"bar"}
Ответ 15
На самом деле это возможно, используя скобки.
const foo = { bar: 1 };
let bar;
({ bar } = foo)
Нашел в эслинте правило предпочтения-уничтожения
Ответ 16
Вы можете уничтожить объект, назначенный непосредственно другому атрибуту объекта.
Рабочий пример:
let user = {};
[user.name, user.username] = "Qaru".split(' ');
document.write('
1st attr: ${user.name} <br />
2nd attr: ${user.username}');
Ответ 17
Ссылаясь на правило "Предпочитать деструктуризацию из массивов и объектов (предпочтение-деструктурирование)" в https://eslint.org/docs/rules/prefer-destructuring, это также возможно:
// define object
let foo;
// destructing
({ foo } = object);