Jak usunąć właściwość z obiektu JavaScript?


6138

Powiedzmy, że tworzę obiekt w następujący sposób:

let myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};

Jaki jest najlepszy sposób, aby usunąć właściwość, regexaby uzyskać nowe myObjectw następujący sposób?

let myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI"
};


@EscapeNetscape To pytanie dotyczy zachowania, więc test porównawczy maluje zły obraz. Oczywiście deletebyłaby to najwolniejsza opcja, ponieważ jest to rzeczywista operacja, a nie dwie pozostałe, które są zwykłymi zadaniami. Ale sedno sprawy polega na tym, że przypisanie właściwości do obiektu nulllub undefinednie usunięcie go z obiektu, ale ustawienie tej właściwości na określoną określoną stałą wartość. (Poniższe odpowiedzi podają powody, dla których jest to znacząca różnica.)
Abion47

Odpowiedzi:


8296

Lubię to:

delete myObject.regex;
// or,
delete myObject['regex'];
// or,
var prop = "regex";
delete myObject[prop];

Próbny

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};
delete myObject.regex;

console.log(myObject);

Dla każdego, kto chce przeczytać więcej na ten temat, użytkownik kangax Stack Overflow napisał niezwykle dokładny post na blogu o deleteoświadczeniu na swoim blogu, Zrozumieć usunięcie . Jest wysoce zalecane.


47
Zaznaczone, działa również z „delete myJSONObject ['regex'];” Zobacz: developer.mozilla.org/en/Core_JavaScript_1.5_Reference/…
johnstok

109
Jedną z obserwacji powyższego linku „zrozumienie usunięcia” jest to, że ponieważ nie można koniecznie usunąć zmiennej, ale tylko właściwości obiektu, nie można zatem usunąć właściwości obiektu „przez odniesienie” - var value = obj [ 'rekwizyt']; usuń wartość // nie działa
Dexygen 16.04.2010

27
Więc to tak naprawdę nie usuwa? Po prostu staje się niezdefiniowany, ale klucz nadal istnieje? Czy coś brakuje?
Doug Molineux,

151
@Pete nie, usuwa to. Biorąc pod uwagę: var x = {a : 'A', b : 'B'};Porównaj: delete x.a; typeof x.a; /* "undefined" */ x.hasOwnProperty('a'); /* false */dox.b = undefined; typeof x.b; /* "undefined" */; x.hasOwnProperty('b'); /* true */
nickf

16
@ChristopherPfohl działa dla mnie. Tak jak powiedziałem, jest dość dogłębny, więc trudno go streścić. Podstawowa odpowiedź zawarta w powyższej odpowiedzi jest wystarczająca dla prawie wszystkich przypadków, blog przechodzi do kilku skrajnych przypadków i powodów, dla których takie przypadki istnieją.
nickf 20.12

952

Obiekty w JavaScript można traktować jak mapy między kluczami a wartościami. deleteOperatora jest stosowane do usuwania tych klawiszy, powszechnie znane jako właściwości obiektu, po jednej na raz.

var obj = {
  myProperty: 1    
}
console.log(obj.hasOwnProperty('myProperty')) // true
delete obj.myProperty
console.log(obj.hasOwnProperty('myProperty')) // false

deleteOperator nie bezpośrednio wolnej pamięci, a różni się od prostego przypisania wartości od nulllub undefinedna obiekcie, że właściwość samo jest usuwany z przedmiotu. Zauważ, że jeśli wartością usuniętej właściwości był typ odwołania (obiekt), a inna część programu nadal zawiera odwołanie do tego obiektu, wówczas obiekt ten nie będzie oczywiście usuwany, dopóki wszystkie odwołania do niego nie będą mieć zniknął.

delete będzie działać tylko w przypadku właściwości, których deskryptor oznacza je jako konfigurowalne.


43
właściwość przypisana do niezdefiniowanej wciąż jest własnością obiektu, więc nie zostanie usunięta przez GC, chyba że źle odczyta ostatni akapit.
Lance,

8
Myliłem się, dotykając tutaj tematu GC. Obie metody mają ten sam wynik dla GC: usuwają wartość powiązaną z kluczem. Gdyby ta wartość była ostatnim odniesieniem do jakiegoś innego obiektu, obiekt ten zostałby wyczyszczony.
Dan

15
właściwość przypisana do niezdefiniowanej wciąż jest własnością obiektu, więc nie zostanie usunięta przez GC GC nie zarządza niczym na temat właściwości. Zbiera i usuwa wartości. Dopóki nic nie odwołuje się już do wartości (obiektu, ciągu itp.), GC usuwa ją z pamięci.
meandre

8
BTW, to jest podwójny problem, aby sprawdzić, czy właściwość istnieje na obiekcie JavaScript. Korzystanie z operatora jest niezawodne, ale wolne. Sprawdź, czy właściwość nie jest niezdefiniowana „nie jest poprawną odpowiedzią”, ale jest o wiele szybsza. sprawdź
rdllopes,

8
Czy ta odpowiedź jest nadal aktualna? jsperf jest obecnie w dół, ale to odniesienia wskazuje na to, że różnica prędkości jest tylko 25%, co jest nawet blisko do „~ 100 razy wolniejszy” w tej odpowiedzi.
Cerbrus

248

var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
    
delete myObject.regex;

console.log ( myObject.regex); // logs: undefined

Działa to w Firefox i Internet Explorer i myślę, że działa we wszystkich innych.


216

deleteOperatora jest stosowane do usuwania właściwości z obiektów.

const obj = { foo: "bar" }
delete obj.foo
obj.hasOwnProperty("foo") // false

Pamiętaj, że w przypadku tablic nie jest to równoznaczne z usunięciem elementu . Aby usunąć element z tablicy, użyj Array#splicelub Array#pop. Na przykład:

arr // [0, 1, 2, 3, 4]
arr.splice(3,1); // 3
arr // [0, 1, 2, 4]

Detale

deletew JavaScript ma inną funkcję niż słowo kluczowe w C i C ++: nie zwalnia bezpośrednio pamięci. Zamiast tego jego jedynym celem jest usunięcie właściwości z obiektów.

W przypadku tablic usunięcie właściwości odpowiadającej indeksowi tworzy tablicę rzadką (tj. Tablicę z „dziurą” w niej). Większość przeglądarek przedstawia te brakujące wskaźniki tablic jako „puste”.

var array = [0, 1, 2, 3]
delete array[2] // [0, 1, empty, 3]

Pamiętaj, że deletenie przenosi się array[3]do array[2].

Różne funkcje wbudowane w JavaScript inaczej przetwarzają rzadkie tablice.

  • for...in całkowicie pominie pusty indeks.

  • Tradycyjna forpętla zwróci undefinedwartość dla indeksu.

  • Każda zastosowana metoda Symbol.iteratorzwróci undefinedwartość dla indeksu.

  • forEach, mapI reducepo prostu pominąć brakujące indeksu.

Tak więc deleteoperator nie powinien być używany do typowego przypadku usuwania elementów z tablicy. Tablice mają dedykowane metody usuwania elementów i ponownego przydzielania pamięci: Array#splice()iArray#pop .

Tablica # splice (start [, deleteCount [, item1 [, item2 [, ...]]]])

Array#splicemutuje tablicę i zwraca wszelkie usunięte indeksy. deleteCountelementy są usuwane z indeksu starti item1, item2... itemNwstawiane do tablicy z indeksu start. Jeśli deleteCountzostanie pominięty, elementy z startIndex są usuwane na końcu tablicy.

let a = [0,1,2,3,4]
a.splice(2,2) // returns the removed elements [2,3]
// ...and `a` is now [0,1,4]

Istnieje również podobnie nazwana, ale inna funkcja Array.prototype:Array#slice .

Array # slice ([start [, end]])

Array#slicejest nieniszczący i zwraca nową tablicę zawierającą wskazane indeksy od startdo end. Jeśli endpozostanie nieokreślony, domyślnie znajdzie się na końcu tablicy. Jeśli endjest dodatni, określa liczony od zera niewłączający indeks, na którym ma się zatrzymać. Jeśli endjest ujemne, określa indeks, na którym ma się zatrzymać, odliczając od końca tablicy (np. -1 pominie indeks końcowy). Jeśli end <= startwynikiem jest pusta tablica.

let a = [0,1,2,3,4]
let slices = [
    a.slice(0,2),
    a.slice(2,2),
    a.slice(2,3),
    a.slice(2,5) ]

//   a           [0,1,2,3,4]
//   slices[0]   [0 1]- - -   
//   slices[1]    - - - - -
//   slices[2]    - -[3]- -
//   slices[3]    - -[2 4 5]

Array # pop

Array#popusuwa ostatni element z tablicy i zwraca ten element. Ta operacja zmienia długość tablicy.


12
Podejście to nie modyfikuje oryginalnego obiektu, do którego wciąż można się odwoływać w innym miejscu. To może, ale nie musi stanowić problemu, w zależności od sposobu jego użycia, ale należy o tym pamiętać.
Tamas Czinege

19
@ B1KMusic Oto sposób na usunięcie elementu z tablicy: splice
wulftone

3
@wulftone nope, która dzieli tablicę i nie robi nic, aby usunąć wartość. Naprawdę uważam, że najlepszym sposobem na usunięcie z tablicy, w której należy usunąć określone wartości, jest użycie deletei wykonanie funkcji czyszczenia pamięci w celu wyczyszczenia.
Braden Best,

5
Nie widzę splicew twoim removeArray.prototype.remove = function(index) { this.splice(index, 1); };
wydaniu

1
Ten artykuł jest pełen byka 1. To nie dotyczy pytania! 2. Jest to przykład niewłaściwego użycia języka i narzeka, że ​​„to nie działa!” 3. Nie obwiniaj operatora usuwania JavaScript za idiosynkratyczny błąd Crockforda polegający na umieszczeniu wartości null dla pustego indeksu tablicy. Nie rozumie znaczenia null - uważa, że ​​to pomyłka. Błąd jest jego własny i sam - w usuniętej wartości danego indeksu tablicy nie ma wartości null. W tablicy nie ma „dziury” - to pusty indeks. Absolutnie uzasadnione i oczekiwane.
Bekim Bacaj

195

Stare pytanie, nowoczesna odpowiedź. Korzystanie z funkcji restrukturyzacji obiektów, funkcji ECMAScript 6 , jest tak prosta, jak:

const { a, ...rest } = { a: 1, b: 2, c: 3 };

Lub z próbką pytań:

const myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
const { regex, ...newObject } = myObject;
console.log(newObject);

Możesz to zobaczyć w akcji w edytorze próbnym Babel.


Edytować:

Aby ponownie przypisać do tej samej zmiennej, użyj let:

let myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
({ regex, ...myObject } = myObject);
console.log(myObject);

6
Może dlatego, że celem jest usunięcie właściwości z obiektu, a nie utworzenie nowej bez właściwości ... chociaż twoje rozwiązanie jest moim ulubionym, ponieważ wolę niezmienny sposób.
Vingt_centimes

8
Pytanie brzmiało: „skończyć z nowym myObject”.
Koen.

1
Dodawanie Underscore do usuwania nieruchomość będzie miot projekt :) Zamiast ona dostępna regexmożna również przypisać do dowolnej innej zmiennej, np _, co jest wykorzystywane w językach takich jak Go odrzucić wynik: const { regex: _, ...newObject } = myObject;.
Koen.

2
@PranayKumar Miałem nadzieję, że ta składnia zadziała; const { [key], ...newObject } = myObject;ale tak nie jest, więc nie sądzę, że jest to możliwe przy restrukturyzacji.
Koen.

2
W przypadku obiektów freeze()„d seal()” nie można po prostu deletewłaściwości. Jest to więc doskonała alternatywa. Chociaż w większości przypadków i tak prawdopodobnie nie ma sensu usuwanie właściwości z zamrożonego / zapieczętowanego obiektu, biorąc pod uwagę, że chodzi o to, aby zapewnić pewne gwarancje dotyczące twoich struktur danych, których wzór ten podważałby. W przypadkach, w których trzeba nieniszcząco zwielokrotnić obiekt, ale bez niektórych jego właściwości, jest to idealne rozwiązanie
Braden Best 3'18

118

Spread Spreadax (ES6)

Ktokolwiek tego potrzebuje ...

Aby wypełnić odpowiedź @Koen w tym wątku, jeśli chcesz usunąć zmienną dynamiczną za pomocą składni spreadu, możesz to zrobić w następujący sposób:

const key = 'a';
        
const { [key]: foo, ...rest } = { a: 1, b: 2, c: 3 };

console.log(foo);  // 1
console.log(rest); // { b: 2, c: 3 }

* foobędzie nową zmienną o wartości a(która wynosi 1).


ROZSZERZONA ODPOWIEDŹ 😇
Istnieje kilka typowych sposobów usuwania właściwości z obiektu.
Każdy ma swoje zalety i wady ( sprawdź to porównanie wydajności ):

Usuń operatora
Czytelny i krótki, jednak może nie być najlepszym wyborem, jeśli operujesz na dużej liczbie obiektów, ponieważ jego wydajność nie jest zoptymalizowana.

delete obj[key];


Zmiana przypisania
Ponad 2 razy szybsza niżdeleteta właściwośćniejestjednakusuwana i może być iterowana.

obj[key] = null;
obj[key] = false;
obj[key] = undefined;


Operator rozprzestrzeniania
TenES6operator pozwala nam zwrócić zupełnie nowy obiekt, z wyłączeniem jakichkolwiek właściwości, bez mutowania istniejącego obiektu. Minusem jest to, że ma gorszą wydajność z powyższego i nie sugeruje się go, gdy trzeba usunąć wiele właściwości na raz.

{ [key]: val, ...rest } = obj;

2
Myślę, że składnia spread / rest dla literałów obiektowych została zawarta tylko w ES2018 (ES9), a nie ES6, mimo że kilka silników JS już ją zaimplementowało.
trincot,

2
@trincot Został wprowadzony po raz pierwszy w 2014 roku ( github.com/tc39/proposal-object-rest-spread ) i jest to funkcja ES6 (ECMAScript 2015 aka ECMAScript 6th Edition). Jednak nawet jeśli się mylę, nie sądzę, że ma to wpływ na kontekst odpowiedzi.
Lior Elrom,

2
Łącze odnosi się do ES6, w którym rzeczywiście wprowadzono składnię rozszerzoną dla tablic, ale nadal proponuje ona coś podobnego dla literałów obiektowych. Ta druga część została włączona do ES9 tylko, jeśli się nie mylę.
trincot,

98

Inną alternatywą jest użycie Underscore.js biblioteki .

Zauważ, że _.pick()i_.omit() obaj powrót kopia obiektu, a nie bezpośrednio modyfikować oryginalnego obiektu. Przypisanie wyniku do oryginalnego obiektu powinno załatwić sprawę (nie pokazano).

Odniesienie: link _.pick (obiekt, * klucze)

Zwraca kopię obiektu przefiltrowaną, aby zawierała tylko wartości kluczy z białej listy (lub tablicy prawidłowych kluczy).

var myJSONObject = 
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

_.pick(myJSONObject, "ircEvent", "method");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};

Odniesienie: link _.omit (obiekt, * klucze)

Zwraca kopię obiektu przefiltrowaną w celu pominięcia kluczy z czarnej listy (lub tablicy kluczy).

var myJSONObject = 
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

_.omit(myJSONObject, "regex");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};

Do tablic _.filter()i _.reject()może być używany w podobny sposób.


4
Należy pamiętać, że jeśli kluczami obiektu są cyfry, być może trzeba_.omit(collection, key.toString())
Jordan Arseno,

Hmmmmm .... Podkreślenie jest ~ 100x wolniejsze niż delete obj[prop]które jest ~ 100x wolniejsze niż obj[prop] = undefined.
Jack Giffin

52

Termin użyty w tytule pytania Remove a property from a JavaScript objectmożna interpretować na kilka różnych sposobów. Jednym z nich jest usunięcie go na całą pamięć i listę kluczy obiektu, a drugim po prostu usunięcie go z obiektu. Jak wspomniano w niektórych innych odpowiedziach,delete słowo kluczowe jest główną częścią. Powiedzmy, że masz swój obiekt, taki jak:

myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

Jeśli zrobisz:

console.log(Object.keys(myJSONObject));

wynik byłby:

["ircEvent", "method", "regex"]

Możesz usunąć ten konkretny klucz ze swoich kluczy obiektowych, takich jak:

delete myJSONObject["regex"];

Następnie użyj klawiszy obiektów Object.keys(myJSONObject) będzie:

["ircEvent", "method"]

Chodzi o to, że jeśli zależy ci na pamięci i chcesz, aby cały obiekt został usunięty z pamięci, zaleca się ustawienie wartości null przed usunięciem klucza:

myJSONObject["regex"] = null;
delete myJSONObject["regex"];

Inną ważną kwestią jest uważanie na inne odniesienia do tego samego obiektu. Na przykład, jeśli utworzysz zmienną taką jak:

var regex = myJSONObject["regex"];

Lub dodaj go jako nowy wskaźnik do innego obiektu, takiego jak:

var myOtherObject = {};
myOtherObject["regex"] = myJSONObject["regex"];

Wtedy nawet jeśli usuniesz go ze swojego obiektu myJSONObject, ten konkretny obiekt nie zostanie usunięty z pamięci, ponieważ regexzmienna imyOtherObject["regex"] ma nadal swoje wartości. Jak więc na pewno moglibyśmy usunąć obiekt z pamięci?

Odpowiedzią byłoby usunięcie wszystkich referencji, które masz w kodzie, wskazanie na ten sam obiekt, a także nie używanie varinstrukcji do tworzenia nowych referencji do tego obiektu . Ten ostatni punkt dotyczący varinstrukcji jest jednym z najważniejszych problemów, z którymi zwykle mamy do czynienia, ponieważ użycie varinstrukcji uniemożliwiłoby usunięcie utworzonego obiektu.

Co oznacza, że ​​w tym przypadku nie będzie można usunąć tego obiektu, ponieważ regexzmienną utworzono za pomocą varinstrukcji, a jeśli to zrobisz:

delete regex; //False

Wynik byłby taki false, co oznacza, że ​​twoja instrukcja usuwania nie została wykonana zgodnie z oczekiwaniami. Ale jeśli wcześniej nie tworzyłeś tej zmiennej, a byłeś tylko myOtherObject["regex"]ostatnim istniejącym odniesieniem, możesz to zrobić, usuwając ją w następujący sposób:

myOtherObject["regex"] = null;
delete myOtherObject["regex"];

Innymi słowy, obiekt JavaScript zostaje zabity, gdy tylko w kodzie nie ma odniesienia do tego obiektu.


Aktualizacja: Dzięki @AgentME:

Ustawienie właściwości na wartość null przed usunięciem niczego nie osiąga (chyba że obiekt został zapieczętowany przez Object.seal i usunięcie się nie powiedzie. Zwykle nie dzieje się tak, chyba że spróbujesz inaczej).

Aby uzyskać więcej informacji na temat Object.seal: Object.seal ()


Mylisz się - tylko obiekty są przekazywane przez JavaScript w referencji, więc jeśli myJSONObject.regexwartość jest łańcuchem i przypisujesz ją do innego obiektu, drugi obiekt ma kopię tej wartości.
Michał Perłakowski

Masz rację i to jest cytat: „uważaj na inne odniesienia do tego samego obiektu”.
Mehran Hatami,

43

ECMAScript 2015 (lub ES6) został wyposażony we wbudowany obiekt Reflect . Możliwe jest usunięcie właściwości obiektu poprzez wywołanie funkcji Reflect.deleteProperty () z obiektem docelowym i kluczem właściwości jako parametrami:

Reflect.deleteProperty(myJSONObject, 'regex');

co jest równoważne z:

delete myJSONObject['regex'];

Ale jeśli właściwości obiektu nie można skonfigurować, nie można go usunąć ani za pomocą funkcji deleteProperty, ani operatora delete:

let obj = Object.freeze({ prop: "value" });
let success = Reflect.deleteProperty(obj, "prop");
console.log(success); // false
console.log(obj.prop); // value

Object.freeze () powoduje, że wszystkie właściwości obiektu nie są konfigurowalne (poza innymi rzeczami). deletePropertyFunkcja (podobnie jak operator usuwania ) zwraca, falsegdy próbuje usunąć dowolną z jej właściwości. Jeśli właściwość jest konfigurowalna, zwraca true, nawet jeśli właściwość nie istnieje.

Różnica między trybem ścisłym deletea deletePropertyjest taka:

"use strict";

let obj = Object.freeze({ prop: "value" });
Reflect.deleteProperty(obj, "prop"); // false
delete obj["prop"];
// TypeError: property "prop" is non-configurable and can't be deleted

1
@Gothdo ma więcej zalet, zwłaszcza gdy musisz zrobić kilka funkcjonalnych rzeczy. Na przykład można przypisać funkcję do zmiennej, należy przekazać jako argument lub użytkowania apply, call, bindfunkcje ...
madox2

41

Załóżmy, że masz obiekt, który wygląda następująco:

var Hogwarts = {
    staff : [
        'Argus Filch',
        'Filius Flitwick',
        'Gilderoy Lockhart',
        'Minerva McGonagall',
        'Poppy Pomfrey',
        ...
    ],
    students : [
        'Hannah Abbott',
        'Katie Bell',
        'Susan Bones',
        'Terry Boot',
        'Lavender Brown',
        ...
    ]
};

Usuwanie właściwości obiektu

Jeśli chcesz korzystać z całej stafftablicy, właściwym sposobem jest zrobienie tego:

delete Hogwarts.staff;

Możesz też to zrobić:

delete Hogwarts['staff'];

Podobnie usunięcie całej tablicy studentów byłoby wykonane przez wywołanie delete Hogwarts.students;lub delete Hogwarts['students'];.

Usuwanie indeksu tablicy

Teraz, jeśli chcesz usunąć jednego członka personelu lub studenta, procedura jest nieco inna, ponieważ obie właściwości są same tablicami.

Jeśli znasz indeks swojego pracownika, możesz po prostu to zrobić:

Hogwarts.staff.splice(3, 1);

Jeśli nie znasz indeksu, musisz również przeprowadzić wyszukiwanie indeksu:

Hogwarts.staff.splice(Hogwarts.staff.indexOf('Minerva McGonnagall') - 1, 1);

Uwaga

Chociaż technicznie możesz użyć deletetablicy, użycie jej spowoduje niepoprawne wyniki podczas wywoływania, na przykład Hogwarts.staff.lengthpóźniej. Innymi słowy, deleteusunąłby element, ale nie zaktualizowałby wartości lengthwłaściwości. Użycie deleterównież popsułoby indeksowanie.

Tak więc, usuwając wartości z obiektu, zawsze najpierw zastanów się, czy masz do czynienia z właściwościami obiektu, czy też z wartościami tablic i wybierz odpowiednią strategię na tej podstawie.

Jeśli chcesz z tym eksperymentować, możesz użyć tego skrzypka jako punktu wyjścia.


Myślę, że zawsze powinieneś używać splicena tablicy zamiast delete.
Joel Trauger

@Jelelrauger: Tak mówię ;-)
John Slegers

Tak. Mój komentarz jest taki, że to deletenie powinno być niczym. Właśnie splicetego szukał OP.
Joel Trauger

1
@JoelTrauger: Jak próbowałem wyjaśnić, deletepowinien być używany do właściwości obiektów i spliceelementów tablicy.
John Slegers

Łączenie jest bardzo wolne. Chociaż powinno się go używać zamiast deletetablic, najrozsądniej byłoby w ogóle nie tworzyć kodu wokół niego.
Jack Giffin

39

Za pomocą ES6:

(Operator restrukturyzacji + spread)

const myObject = {
    regex: "^http://.*",
    b: 2,
    c: 3
};
const { regex, ...noRegex } = myObject;
console.log(noRegex); // => { b: 2, c: 3 }

Nie sądzę, że jest to funkcja ES6, ale ta, która została uwzględniona tylko w ES9.
trincot,

Więc tak naprawdę nie używasz ES6, jak piszesz, ale ES9 ... ;-)
trincot

2
Nie oznacza to usunięcia właściwości z obiektu, ale utworzenie nowego obiektu bez tej właściwości.
Jordi Nebot,



29

Aby sklonować obiekt bez właściwości:

Na przykład:

let object = { a: 1, b: 2, c: 3 };   

I musimy usunąć „a”.

1.Z wyraźnym kluczem prop:

const { a, ...rest } = object;
object = rest;

2. Ze zmiennym kluczem prop:

const propKey = 'a';
const { [propKey]: propValue, ...rest } = object;
object = rest;

3. funkcja strzałki Cool ool:

const removePropery = (propKey, { [propKey]: propValue, ...rest }) => rest;

object = removePropery('a', object);

4. W przypadku wielu właściwości

const removeProperties = (object, ...keys) => Object.entries(object).reduce((prev, [key, value]) => ({...prev, ...(!keys.includes(key) && { [key]: value }) }), {})

Stosowanie

object = removeProperties(object, 'a', 'b') // result => { c: 3 }

Lub

    const propsToRemove = ['a', 'b']
    object = removeProperties(object, ...propsToRemove) // result => { c: 3 }

1
Zręczna funkcja strzałki!
JSilv

27

Najlepszą metodą jest użycie metody delete , zgodnie z opisem MDN operator delete usuwa właściwość z obiektu. Możesz więc po prostu napisać:

delete myObject.regex;
// OR
delete myObject['regex'];

Operator delete usuwa daną właściwość z obiektu. Po pomyślnym usunięciu zwróci true, w przeciwnym razie false zostanie zwrócony. Należy jednak wziąć pod uwagę następujące scenariusze:

  • Jeśli właściwość, którą próbujesz usunąć, nie istnieje, usunięcie nie będzie miało żadnego skutku i zwróci wartość true

  • Jeśli właściwość o tej samej nazwie istnieje w łańcuchu prototypów obiektu, to po usunięciu obiekt użyje właściwości z łańcucha prototypów (innymi słowy, usunięcie ma wpływ tylko na własne właściwości).

  • Żadnej właściwości zadeklarowanej za pomocą var nie można usunąć z zakresu globalnego ani z zakresu funkcji.

  • W związku z tym delete nie może usuwać żadnych funkcji w zakresie globalnym (niezależnie od tego, czy jest to część definicji funkcji, czy funkcja (wyrażenie).

  • Funkcje, które są częścią obiektu (oprócz
    zasięgu globalnego), można usunąć za pomocą delete.

  • Żadnej właściwości zadeklarowanej za pomocą let lub const nie można usunąć z zakresu, w którym zostały zdefiniowane. Nie można skonfigurować właściwości, których nie można konfigurować. Obejmuje to właściwości wbudowanych obiektów, takich jak Math, Array, Object oraz właściwości, które są tworzone jako nieskonfigurowalne za pomocą metod takich jak Object.defineProperty ().

Poniższy fragment kodu stanowi kolejny prosty przykład:

var Employee = {
      age: 28,
      name: 'Alireza',
      designation: 'developer'
    }
    
    console.log(delete Employee.name);   // returns true
    console.log(delete Employee.age);    // returns true
    
    // When trying to delete a property that does 
    // not exist, true is returned 
    console.log(delete Employee.salary); // returns true

Aby uzyskać więcej informacji i zobaczyć więcej przykładów, kliknij poniższy link:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete


22

Inne rozwiązanie, przy użyciu Array#reduce.

var myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};

myObject = Object.keys(myObject).reduce(function(obj, key) {
  if (key != "regex") {           //key you want to remove
    obj[key] = myObject[key];
  }
  return obj;
}, {});

console.log(myObject);

Jednak spowoduje to mutację oryginalnego obiektu. Jeśli chcesz utworzyć nowy obiekt bez określonego klucza, po prostu przypisz funkcję redukcji do nowej zmiennej, np .:

(ES6)

const myObject = {
  ircEvent: 'PRIVMSG',
  method: 'newURI',
  regex: '^http://.*',
};

const myNewObject = Object.keys(myObject).reduce((obj, key) => {
  key !== 'regex' ? obj[key] = myObject[key] : null;
  return obj;
}, {});

console.log(myNewObject);


21

Ten post jest bardzo stary i uważam, że jest bardzo pomocny, dlatego zdecydowałem się udostępnić napisaną przeze mnie funkcję rozbrojenia, na wypadek, gdyby ktoś zobaczył ten post i pomyślał, dlaczego nie jest tak prosty, jak w przypadku PHP.

Powodem napisania tej nowej unsetfunkcji jest utrzymanie indeksu wszystkich innych zmiennych w tej hash_map. Spójrz na następujący przykład i zobacz, jak indeks „test2” nie zmienił się po usunięciu wartości z hash_map.

function unset(unsetKey, unsetArr, resort){
  var tempArr = unsetArr;
  var unsetArr = {};
  delete tempArr[unsetKey];
  if(resort){
    j = -1;
  }
  for(i in tempArr){
    if(typeof(tempArr[i]) !== 'undefined'){
      if(resort){
        j++;
      }else{
        j = i;
      }
      unsetArr[j] = tempArr[i];
    }
  }
  return unsetArr;
}

var unsetArr = ['test','deletedString','test2'];

console.log(unset('1',unsetArr,true)); // output Object {0: "test", 1: "test2"}
console.log(unset('1',unsetArr,false)); // output Object {0: "test", 2: "test2"}

20

Istnieje tutaj wiele dobrych odpowiedzi, ale chcę tylko zadzwonić, gdy przy usuwaniu właściwości w JavaScript używam delete, często mądrze jest najpierw sprawdzić, czy ta właściwość istnieje, aby zapobiec błędom.

Na przykład

var obj = {"property":"value", "property2":"value"};

if (obj && obj.hasOwnProperty("property2")) {
  delete obj.property2;
} else {
  //error handling
}

Ze względu na dynamiczny charakter JavaScript często zdarza się, że po prostu nie wiesz, czy dana właściwość istnieje, czy nie. Sprawdzanie, czy obiekt istnieje przed &&, zapewnia również, że nie wyrzucisz błędu z powodu wywołania funkcji hasOwnProperty () na niezdefiniowanym obiekcie.

Przykro nam, jeśli nie dodało to konkretnego przypadku użycia, ale uważam, że jest to dobry projekt do dostosowania podczas zarządzania obiektami i ich właściwościami.


2
delete foo.bar działa nawet jeśli pasek nie istnieje, więc twój test to trochę za dużo, IMHO.
PhiLho

@PhiLho, które zależy od tego, gdzie używasz JavaScript. Uważam, że w Node.js powoduje to awarię serwera.
Willem,

2
delete foo.bar;zgłasza wyjątek tylko wtedy, gdy foo jest fałszem lub jeśli jesteś w trybie ścisłym, a foo jest obiektem z nieskonfigurowaną właściwością bar.
Macil

Nie pamiętam dokładnego problemu z tym, ale myślę, że problem może pojawić się, gdy sam foo nie istnieje i próbujesz usunąć jego własność.
Willem,

Tak, musisz sprawdzić, czy istnieje foo, w przeciwnym razie foo.bar zgłosi wyjątek, ale nie musisz sprawdzać istnienia paska przed usunięciem. To jest „za dużo” części mojego komentarza. :-)
PhiLho

16

Używając ramda # dissoc otrzymasz nowy obiekt bez atrybutu regex:

const newObject = R.dissoc('regex', myObject);
// newObject !== myObject

Możesz także użyć innych funkcji, aby osiągnąć ten sam efekt - pomiń, wybierz, ...


15

Wypróbuj następującą metodę. Przypisz Objectwartość właściwości do undefined. Następnie stringifyobiekt i parse.

 var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

myObject.regex = undefined;
myObject = JSON.parse(JSON.stringify(myObject));

console.log(myObject);


1
RównieżJSON.parse(JSON.stringify({ ...myObject, regex: undefined }))
noisypixy

12

Jeśli chcesz usunąć właściwość głęboko zagnieżdżoną w obiekcie, możesz użyć następującej funkcji rekurencyjnej ze ścieżką do właściwości jako drugiego argumentu:

var deepObjectRemove = function(obj, path_to_key){
    if(path_to_key.length === 1){
        delete obj[path_to_key[0]];
        return true;
    }else{
        if(obj[path_to_key[0]])
            return deepObjectRemove(obj[path_to_key[0]], path_to_key.slice(1));
        else
            return false;
    }
};

Przykład:

var a = {
    level1:{
        level2:{
            level3: {
                level4: "yolo"
            }
        }
    }
};

deepObjectRemove(a, ["level1", "level2", "level3"]);
console.log(a);

//Prints {level1: {level2: {}}}

Ta funkcja działa jak urok, ale dlaczego potrzebujemy zwrócić true i return false? Moja wersja kodu: codepen.io/anon/pen/rwbppY . Czy moja wersja w żadnym wypadku się nie powiedzie?
niezwykły

@ witty2017 to nie zawiedzie. Miejsce, w którym użyłem tej funkcji, również musiało sprawdzić, czy właściwość już istnieje, czy nie. jeśli właściwość nie istnieje, zwróci false. Jeśli znajdzie właściwość i ją usunie, zwróci wartość true.
ayushgp 17.07.17

8

Możesz po prostu usunąć dowolną właściwość obiektu za pomocą deletesłowa kluczowego.

Na przykład:

var obj = {key1:"val1",key2:"val2",key3:"val3"}

Aby usunąć dowolną właściwość, powiedzmy key1, użyj deletesłowa kluczowego takiego:

delete obj.key1

Możesz też użyć notacji tablicowej:

delete obj[key1]

Ref: MDN .


8

Object.assign () i Object.keys () & Array.map ()

const obj = {
    "Filters":[
        {
            "FilterType":"between",
            "Field":"BasicInformationRow.A0",
            "MaxValue":"2017-10-01",
            "MinValue":"2017-09-01",
            "Value":"Filters value"
        }
    ]
};

let new_obj1 = Object.assign({}, obj.Filters[0]);
let new_obj2 = Object.assign({}, obj.Filters[0]);

/*

// old version

let shaped_obj1 = Object.keys(new_obj1).map(
    (key, index) => {
        switch (key) {
            case "MaxValue":
                delete new_obj1["MaxValue"];
                break;
            case "MinValue":
                delete new_obj1["MinValue"];
                break;
        }
        return new_obj1;
    }
)[0];


let shaped_obj2 = Object.keys(new_obj2).map(
    (key, index) => {
        if(key === "Value"){
            delete new_obj2["Value"];
        }
        return new_obj2;
    }
)[0];


*/


// new version!

let shaped_obj1 = Object.keys(new_obj1).forEach(
    (key, index) => {
        switch (key) {
            case "MaxValue":
                delete new_obj1["MaxValue"];
                break;
            case "MinValue":
                delete new_obj1["MinValue"];
                break;
            default:
                break;
        }
    }
);

let shaped_obj2 = Object.keys(new_obj2).forEach(
    (key, index) => {
        if(key === "Value"){
            delete new_obj2["Value"];
        }
    }
);


7

Twierdzenie Dana, że ​​„usuń” jest bardzo powolne, a opublikowany przez niego punkt odniesienia był wątpliwy. Więc sam przeprowadziłem test w Chrome 59. Wygląda na to, że „usuwanie” jest około 30 razy wolniejsze:

var iterationsTotal = 10000000;  // 10 million
var o;
var t1 = Date.now(),t2;
for (let i=0; i<iterationsTotal; i++) {
   o = {a:1,b:2,c:3,d:4,e:5};
   delete o.a; delete o.b; delete o.c; delete o.d; delete o.e;
}
console.log ((t2=Date.now())-t1);  // 6135
for (let i=0; i<iterationsTotal; i++) {
   o = {a:1,b:2,c:3,d:4,e:5};
   o.a = o.b = o.c = o.d = o.e = undefined;
}
console.log (Date.now()-t2);  // 205

Zauważ, że celowo przeprowadziłem więcej niż jedną operację „usuń” w jednym cyklu pętli, aby zminimalizować efekt spowodowany przez inne operacje.


7

Zastanów się nad utworzeniem nowego obiektu bez "regex"właściwości, ponieważ do oryginalnego obiektu zawsze mogą odnosić się inne części programu. Dlatego należy unikać manipulowania nim.

const myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};

const { regex, ...newMyObject } = myObject;

console.log(newMyObject);


SyntaxError: Unexpected token '...'. Expected a property name.?
Krzysztof Przygoda

Wypróbuj w nowoczesnej przeglądarce, takiej jak Firefox, Chromium lub Safari. I spodziewam się, że zadziała również z Edge.
ideaboxer

Alternatywnie, jeśli Twoi klienci zmuszają Cię do obsługi przestarzałych przeglądarek, możesz rozważyć użycie TypeScript, który transponuje Twój kod do starszej składni (+ daje Ci korzyść z bezpieczeństwa typu statycznego).
ideaboxer

7

Usuwanie nieruchomości w JavaScript

Na tej stronie znajduje się wiele różnych opcji, nie dlatego, że większość opcji jest błędna - lub ponieważ odpowiedzi są duplikatami - ale dlatego, że odpowiednia technika zależy od sytuacji, w której się znajdujesz i celów zadań, które Ty i / lub Ty zespół stara się spełnić. Aby odpowiedzieć na twoje pytanie jednoznacznie, musisz wiedzieć:

  1. Wersja ECMAScript, na którą celujesz
  2. Zakres typów obiektów, na których chcesz usunąć właściwości, oraz rodzaj nazw właściwości, które musisz pominąć (tylko ciągi znaków? Symbole? Słabe referencje odwzorowane z dowolnych obiektów? Od lat wszystkie typy wskaźników właściwości w JavaScript )
  3. Etos programowania / wzorce, których używasz Ty i Twój zespół. Czy faworyzujesz podejście funkcjonalne, a mutacja jest w twoim zespole werbalna, czy używasz technik obiektowych zorientowanych na mutacje na dzikim zachodzie?
  4. Czy chcesz to osiągnąć w czystym JavaScript, czy chcesz i możesz korzystać z biblioteki innej firmy?

Po udzieleniu odpowiedzi na te cztery pytania istnieją zasadniczo cztery kategorie „usuwania właściwości” w JavaScript, które można wybrać, aby osiągnąć swoje cele. Oni są:

Usuwanie właściwości obiektu mutującego, niebezpieczne

Ta kategoria służy do operowania literałami obiektów lub instancjami obiektów, gdy chcesz zachować / kontynuować używanie oryginalnego odwołania i nie używasz funkcjonalnych zasad bezstanowych w kodzie. Przykład składni w tej kategorii:

'use strict'
const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true }
delete iLikeMutatingStuffDontI[Symbol.for('amICool')] // true
Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false })
delete iLikeMutatingStuffDontI['amICool'] // throws

Ta kategoria jest najstarszą, najprostszą i najczęściej wspieraną kategorią usuwania nieruchomości. Obsługuje Symboli indeksy tablic oprócz ciągów i działa w każdej wersji JavaScript z wyjątkiem pierwszej wersji. Jest to jednak mutacja, która narusza niektóre zasady programowania i ma wpływ na wydajność. Może także powodować nieprzechwycone wyjątki, gdy zostanie użyty w przypadku właściwości nieskonfigurowanych w trybie ścisłym .

Pominięcie właściwości ciągu opartego na reszcie

Ta kategoria jest przeznaczona do działania na instancjach zwykłych obiektów lub tablic w nowszych wersjach ECMAScript, gdy pożądane jest podejście niemutujące i nie trzeba uwzględniać kluczy symboli:

const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true }
const { name, ...coolio } = foo // coolio doesn't have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn't account for Symbols :(

Usuwanie właściwości obiektu mutującego, bezpieczne

Ta kategoria jest przeznaczona do operowania literałami obiektów lub instancjami obiektów, gdy chcesz zachować / kontynuować używanie oryginalnego odwołania, jednocześnie chroniąc przed wyjątkami zgłaszanymi przez nieskonfigurowalne właściwości:

'use strict'
const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true }
Reflect.deleteProperty(iLikeMutatingStuffDontI, Symbol.for('amICool')) // true
Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false })
Reflect.deleteProperty(iLikeMutatingStuffDontI, 'amICool') // false

Ponadto, podczas gdy mutowanie obiektów w miejscu nie jest bezstanowe, możesz użyć funkcjonalnej natury Reflect.deletePropertyczęściowej aplikacji i innych technik funkcjonalnych, które nie są możliwe w przypadku deleteinstrukcji.

Pominięcie właściwości ciągu na podstawie składni

Ta kategoria jest przeznaczona do działania na instancjach zwykłych obiektów lub tablic w nowszych wersjach ECMAScript, gdy pożądane jest podejście niemutujące i nie trzeba uwzględniać kluczy symboli:

const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true }
const { name, ...coolio } = foo // coolio doesn't have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn't account for Symbols :(

Pominięcie właściwości na podstawie biblioteki

Ta kategoria ogólnie pozwala na większą elastyczność funkcjonalną, w tym rozliczanie symboli i pomijanie więcej niż jednej właściwości w jednym zestawieniu:

const o = require("lodash.omit")
const foo = { [Symbol.for('a')]: 'abc', b: 'b', c: 'c' }
const bar = o(foo, 'a') // "'a' undefined"
const baz = o(foo, [ Symbol.for('a'), 'b' ]) // Symbol supported, more than one prop at a time, "Symbol.for('a') undefined"

var keyname = "KeyName"; usuń myObject [nazwa klucza];
Vikash Chauhan,

7

const myObject = {
        "ircEvent": "PRIVMSG",
        "method": "newURI",
        "regex": "^http://.*"
    };

const { regex, ...other } = myObject;

console.log(myObject)
console.log(regex)
console.log(other)


@CoddWrench Przepraszamy, nie zwracałem uwagi na odpowiedź. Odpowiadam na to natychmiast po obejrzeniu delete myObject.regex;.
xiang

7

Możesz użyć restrukturyzacji ES6 z operatorem odpoczynku.

Właściwości można usunąć za pomocą destrukcji w połączeniu z operatorem reszty . W twoim przykładzie wyrażenie regularne jest zniszczone (ignorowane), a reszta właściwości jest zwracana jako reszta.

const noRegex = ({ regex, ...rest }) => rest;
const myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};

console.log(noRegex(myObjext)) //=> {  "ircEvent": "PRIVMSG","method": "newURI" }

Możesz też dynamicznie wykluczyć takie właściwości,

const myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};
const removeProperty = prop => ({ [prop]: _, ...rest }) => rest

const removeRegex = removeProperty('regex') //=> {  "ircEvent": "PRIVMSG","method":"newURI" }
const removeMethod = removeProperty('method') //=> {  "ircEvent": "PRIVMSG", "regex":"^http://.*" }

7

Możemy usunąć dowolną właściwość z obiektu javascript za pomocą:

  1. usuń object.property
  2. usuń obiekt [„właściwość”]

przykład:

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};

console.log(myObject);

delete myObject.regex;
console.log('=================');
console.log(myObject);
delete myObject['method'];
console.log('=================');
console.log(myObject);


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.