Jaki jest dobry i krótki sposób na usunięcie wartości z obiektu o określonym kluczu bez mutowania oryginalnego obiektu?
Chciałbym zrobić coś takiego:
let o = {firstname: 'Jane', lastname: 'Doe'};
let o2 = doSomething(o, 'lastname');
console.log(o.lastname); // 'Doe'
console.log(o2.lastname); // undefined
Wiem, że istnieje wiele bibliotek niezmienności do takich zadań, ale chciałbym uciec bez biblioteki. Jednak aby to zrobić, wymagałoby to łatwego i krótkiego sposobu, który może być używany w całym kodzie, bez abstrahowania metody jako funkcji użyteczności.
Np. Aby dodać wartość, wykonuję następujące czynności:
let o2 = {...o1, age: 31};
Jest to dość krótkie, łatwe do zapamiętania i nie wymaga funkcji narzędziowej.
Czy jest coś takiego do usuwania wartości? ES6 jest bardzo mile widziane.
Dziękuję Ci bardzo!
javascript
immutability
amann
źródło
źródło
Odpowiedzi:
Aktualizacja:
Możesz usunąć właściwość z obiektu za pomocą trudnego przypisania Destrukturyzacja :
const doSomething = (obj, prop) => { let {[prop]: omit, ...res} = obj return res }
Jeśli jednak nazwa właściwości, którą chcesz usunąć, jest statyczna, możesz ją usunąć za pomocą prostego, jednowierszowego:
let {lastname, ...o2} = o
Najłatwiej jest po prostulub możesz sklonować obiekt przed jego mutacją:const doSomething = (obj, prop) => { let res = Object.assign({}, obj) delete res[prop] return res }
Alternatywnie możesz użyć
omit
funkcji zlodash
biblioteki narzędziowej :let o2 = _.omit(o, 'lastname')
Jest dostępny jako część pakietu lodash lub jako samodzielny pakiet lodash.omit .
źródło
a2 = a1.filter(el => el.id !== id)
pominąć element w tablicy za pomocą określonego identyfikatora. Czy nie ma czegoś takiego dla przedmiotu?keep_if
const {[prop], ...rest} = obj
działa? Dlaczego musisz przypisać wyodrębnioną właściwość do nowej zmiennej (omit
w tym przypadku)?no-unused-vars
reguły „pomiń” lub „pominięty” , to po prostu wyrażenie regularne.Dzięki destrukturyzacji obiektów ES7:
const myObject = { a: 1, b: 2, c: 3 }; const { a, ...noA } = myObject; console.log(noA); // => { b: 2, c: 3 }
źródło
a
jest przechowywany w zmiennejconst x = 'a'
?const { a,b, ...noA } = myObject;
console.log(noA); // => {c: 3 }
rozwiązanie jednoprzewodowe
const removeKey = (key, {[key]: _, ...rest}) => rest;
źródło
Jak zasugerowano w komentarzach powyżej, jeśli chcesz to przedłużyć, aby usunąć więcej niż jeden element z Twojego,
object
którego lubię używaćfilter
. ireduce
na przykład
const o = { "firstname": "Jane", "lastname": "Doe", "middlename": "Kate", "age": 23, "_id": "599ad9f8ebe5183011f70835", "index": 0, "guid": "1dbb6a4e-f82d-4e32-bb4c-15ed783c70ca", "isActive": true, "balance": "$1,510.89", "picture": "http://placehold.it/32x32", "eyeColor": "green", "registered": "2014-08-17T09:21:18 -10:00", "tags": [ "consequat", "ut", "qui", "nulla", "do", "sunt", "anim" ] }; const removeItems = ['balance', 'picture', 'tags'] console.log(formatObj(o, removeItems)) function formatObj(obj, removeItems) { return { ...Object.keys(obj) .filter(item => !isInArray(item, removeItems)) .reduce((newObj, item) => { return { ...newObj, [item]: obj[item] } }, {}) } } function isInArray(value, array) { return array.indexOf(value) > -1; }
źródło
Aby dodać pikanterii wprowadzając Performance. Sprawdź ten wątek poniżej
https://github.com/googleapis/google-api-nodejs-client/issues/375
Możesz też użyć niszczycielskiego sposobu
const {remov1, remov2, ...new} = old; old = new;
I bardziej praktyczny przykład:
this._volumes[this._minCandle] = undefined; { const {[this._minCandle]: remove, ...rest} = this._volumes; this._volumes = rest; }
Jak widać, możesz użyć
[somePropsVarForDynamicName]: scopeVarName
w nazwach dynamicznych składni. I możesz umieścić wszystko w nawiasach (nowy blok), aby reszta została po nim zebrana.Tutaj test:
exec:
Lub możemy skorzystać z jakiejś funkcji, takiej jak
function deleteProps(obj, props) { if (!Array.isArray(props)) props = [props]; return Object.keys(obj).reduce((newObj, prop) => { if (!props.includes(prop)) { newObj[prop] = obj[prop]; } return newObj; }, {}); }
dla maszynopisu
function deleteProps(obj: Object, props: string[]) { if (!Array.isArray(props)) props = [props]; return Object.keys(obj).reduce((newObj, prop) => { if (!props.includes(prop)) { newObj[prop] = obj[prop]; } return newObj; }, {}); }
Stosowanie:
let a = {propH: 'hi', propB: 'bye', propO: 'ok'}; a = deleteProps(a, 'propB'); // or a = deleteProps(a, ['propB', 'propO']);
W ten sposób powstaje nowy obiekt. I zachowana jest szybka właściwość obiektu. Co może być ważne lub ważne. Jeśli mapowanie i obiekt będą dostępne wiele razy.
Kojarzenie się
undefined
może być również dobrym sposobem. Kiedy możesz sobie na to pozwolić. W przypadku kluczy możesz też sprawdzić wartość. Na przykład, aby uzyskać wszystkie aktywne klucze, wykonaj coś takiego:const allActiveKeys = Object.keys(myObj).filter(k => myObj[k] !== undefined); //or const allActiveKeys = Object.keys(myObj).filter(k => myObj[k]); // if any false evaluated value is to be stripped.
Niezdefiniowany nie nadaje się jednak na dużą listę. Lub rozwój w czasie z wieloma rekwizytami, które pojawią się. Ponieważ użycie pamięci będzie rosło i nigdy nie zostanie wyczyszczone. Więc to zależy od użycia. A samo stworzenie nowego obiektu wydaje się być dobrym sposobem.
Wtedy
Premature optimization is the root of all evil
zadziała. Musisz więc być świadomy tego kompromisu. A co jest potrzebne, a co nie.Uwaga dotycząca _.omit () z lodash
Został usunięty z wersji 5. Nie możesz go znaleźć w repozytorium. I tutaj kwestia, która o tym mówi.
https://github.com/lodash/lodash/issues/2930
v8
Możesz to sprawdzić, co jest dobrym lekturą https://v8.dev/blog/fast-properties
źródło
Mój problem z zaakceptowaną odpowiedzią, ze standardu reguł ESLint, jeśli próbujesz zniszczyć:
const { notNeeded, alsoNotNeeded, ...rest } = { ...ogObject };
dwie nowe zmienne
notNeeded
ialsoNotNeeded
mogą generować ostrzeżenie lub błąd w zależności od konfiguracji, ponieważ są teraz nieużywane. Po co więc tworzyć nowe zmienne, jeśli nie są używane?Myślę, że naprawdę musisz użyć tej
delete
funkcji.źródło
no-unused-vars
Przepis rzeczywiście ma możliwośćignoreRestSiblings
teraz, aby pokryć ten przypadek użycia: eslint.org/docs/rules/no-unused-vars#ignorerestsiblingsz lodash cloneDeep i delete
(uwaga: klon lodash może być używany zamiast płytkich obiektów)
const obj = {a: 1, b: 2, c: 3} const unwantedKey = 'a' const _ = require('lodash') const objCopy = _.cloneDeep(obj) delete objCopy[unwantedKey] // objCopy = {b: 2, c: 3}
źródło
Dla mojego kodu potrzebowałem skróconej wersji dla wartości zwracanej przez map (), ale rozwiązania operacji multiline / mutli były „brzydkie”. Kluczową cechą jest to,
void(0)
co stare, które postanawiająundefined
.let o2 = {...o, age: 31, lastname: void(0)};
Nieruchomość pozostaje w obiekcie:
console.log(o2) // {firstname: "Jane", lastname: undefined, age: 31}
ale struktura transmisji zabija to za mnie (bc stringify):
console.log(JSON.stringify(o2)) // {"firstname":"Jane","age":31}
źródło