Питання Як видалити властивість з об'єкта JavaScript?


Скажімо, я створюю об'єкт таким чином:

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

Який найкращий спосіб видалити майно regex в кінцевому підсумку з новим myObject як слід?

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

4910
2017-10-16 10:57


походження


Знайдіть тут тест, який порівнює "видалити" і "невизначене" проти "нуль" jsben.ch/#/BWMiw - EscapeNetscape
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - titusfx


Відповіді:


Подобається це:

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

Демонстрація

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

console.log(myObject);

Для всіх, хто зацікавлений в тому, щоб більше дізнатися про це, користувач Stack Overflow кангакс написав неймовірно поглиблену публікацію блогу про delete заява на своєму блозі Розуміння видалення. Це дуже рекомендується.


6839
2017-10-16 10:58



Перевірено, він також працює з "видалити myJSONObject ['regex'];" Побачити: developer.mozilla.org/en/Core_JavaScript_1.5_Reference/... - johnstok
Підсумок однієї з спостережень, наведених вище в "розумінні видалення", полягає в тому, що оскільки ви не можете обов'язково видалити змінну, а лише властивості об'єкта, ви не можете видалити властивість об'єкта "за посиланням" - var value = obj [ 'prop']; видалити значення // не працює - George Jempty
Так що це фактично не видаляє його? Це просто стає невизначеною, але ключ все ще існує? Чи мені щось не вистачає? - Doug Molineux
@ Pete ні, це видаляє його. Дано: var x = {a : 'A', b : 'B'}; Порівняйте: delete x.a; typeof x.a; /* "undefined" */ x.hasOwnProperty('a'); /* false */ до x.b = undefined; typeof x.b; /* "undefined" */; x.hasOwnProperty('b'); /* true */ - nickf
@ ChristopherPofoh працює для мене. Як я вже сказав, це насправді досить поглиблене, так що це трохи важко узагальнити. Базова відповідь у відповідь вище є достатньою для майже всіх випадків, блог висвітлюється ще в кількох регіонах, і причини цих випадків існують. - nickf


Оператор delete несподівано повільний!

Подивись на орієнтир.

Видалити є єдиним вірним способом видалення властивостей об'єкта без залишків, але це працює ~ 100 разів повільніше, в порівнянні з його "альтернативою", налаштуванням object[key] = undefined.

Ця альтернатива не є правильною відповіддю на це питання! Але якщо ви використовуєте його з турботою, ви можете різко прискорити деякі алгоритми. Якщо ви використовуєте delete у циклах, і у вас є проблеми з продуктивністю, прочитайте докладне пояснення.

Коли треба користуватися delete і коли встановлено значення до undefined ?

Об'єкт може розглядатися як сукупність пар ключ-значення. Те, що я називаю «значенням», є примітивним або посиланням на інший об'єкт, пов'язаний з цим «ключем».

Використовуйте delete, коли ви передаєте об'єкт результату до коду, на якому ви не маєте контролю (або коли ви не впевнені щодо вашої команди або себе).

Це видаляє ключ з хешпапу.

 var obj = {
     field: 1     
 };
 delete obj.field;

Використовуйте налаштування для undefined, коли ви дбаєте про продуктивність. Це може серйозно прискорити ваш код.

The ключ залишається на своєму місці в хеш-карти, значення замінюється лише значенням undefined. Зрозумій це for..in цикл буде продовжувати ітерації над цим ключем.

 var obj = {
     field: 1     
 };
 obj.field = undefined;

Використовуючи цей метод, не все способи визначення майна існування буде працювати, як очікується.

Однак цей код:

object.field === undefined

буде вести себе аналогічно для обох методів.

Тести

Підбиваючи підсумок, всі відмінності - це способи визначення існування власності, а про for..in петля

 console.log('* -> "Takes prototype inheritance into consideration, that means it lookups all over prototype chain too."');

 console.log(obj.field === undefined, 'obj.field === undefined', 'You get "undefined" value when querying for "field" in object-hashmap. *');

 console.log(obj["field"] === undefined, 'obj["field"] === undefined', 'Just another way to query (equivalent). *');

 console.log(typeof obj.field === "undefined", 'typeof obj.field === "undefined"', 'Get the value attached to "field" key, and check it\'s type is "undefined". *');

 console.log("field" in obj, '"field" in obj', 'This statement returns true if "field" key exists in the hashmap. False otherwise. *');

 console.log(obj.hasOwnProperty("field"), 'obj.hasOwnProperty("field")', 'This statement returns true if \'field\' key exists in the hashmap. The ONLY way NOT to lookup for property in the prototype chain!');
 //Object.keys().indexOf() is an overkill that runs much slower :)

 var counter = 0,
     key;
 for (key in obj) {
     counter++;
 }
 console.assert(counter === 0, 'counter === 0', '"field" is not iterated using "for .. in" loop. *');

Остерігайтеся витоків пам'яті!

Під час використання obj[prop] = undefined швидше, ніж робити delete obj[prop], ще одне важливе значення - це obj[prop] = undefined може не завжди бути доречним. delete obj[prop] видаляє prop від obj і стирає його з пам'яті, тоді як obj[prop] = undefined просто встановлює значення prop до undefined який залишає prop все ще в пам'яті. Тому, в умовах, коли багато ключів створюються та видаляються, використовуючи obj[prop] = undefined може змусити дорогову суміш пам'яті (змушуючи сторінку зависати) і потенційно помилку поза пам'яттю. Перевірте наступний код.

"use strict";
var theNodeList=[], i, current, numberOfNodes=65536, body=document.body, nodeRecords=[];
for (i = 0; i !== numberOfNodes; i++) {
    nodeRecords[i] = [];
    current = theNodeList[i] = document.createElement("div");
    current.textContent = i;
    document.body.appendChild( current );
}
var lastTime = -1;
requestAnimationFrame(function recordUpdates(){
    var currentTime = Math.round( performance.now()*1000 )
    for (i = 0; i !== numberOfNodes; i++) {
        if (lastTime !== -1) {
            // the previously collected data is no longer in use
            /*************************************************/
            /****/ nodeRecords[i][lastTime] = undefined; /****/
            /*************************************************/
        }
        nodeRecords[i][currentTime] = theNodeList[i].outerHTML;
    }
    lastTime = currentTime;
    requestAnimationFrame( recordUpdates );
});

У наведеному вище коді просто робити nodeRecords[i][lastTime] = undefined; призведе до витікання величезної пам'яті через кожен кадр анімації. У кожному кадрі всі 65536 елементів DOM матимуть ще 65536 окремих слотів, але попередні слоти 65536 будуть встановлені лише як невизначені, що залишить їх у пам'яті. Продовжуйте спробувати запустити вказаний вище код в консолі і побачити самі. Після того, як виникла помилка поза пам'яттю, спробуйте запустити її знову, за винятком наступної версії коду, що використовує deleteОператор замість.

"use strict";
var theNodeList=[], i, current, numberOfNodes=65536, body=document.body, nodeRecords=[];
for (i = 0; i !== numberOfNodes; i++) {
    nodeRecords[i] = [];
    current = theNodeList[i] = document.createElement("div");
    current.textContent = i;
    document.body.appendChild( current );
}
var lastTime = -1;
requestAnimationFrame(function recordUpdates(){
    var currentTime = Math.round( performance.now()*1000 )
    for (i = 0; i !== numberOfNodes; i++) {
        if (lastTime !== -1) {
            // the previously collected data is no longer in use
            /********************************************/
            /****/ delete nodeRecords[i][lastTime]; /****/
            /********************************************/
        }
        nodeRecords[i][currentTime] = theNodeList[i].outerHTML;
    }
    lastTime = currentTime;
    requestAnimationFrame( recordUpdates );
});

Як видно з наведеного вище фрагмента коду, є деякі рідкісні випадки використання для delete оператор Проте не хвилюйтеся про цю проблему занадто багато. Це стане лише проблемою з об'єктами довгого життя, які постійно додають нові ключі. У будь-якому іншому випадку (що майже у кожному випадку в реальному світі програмування), найбільш прийнятним є використання obj[prop] = undefined. Основна мета цього розділу полягає лише в тому, щоб привернути це до вашого відома, так що в рідкісних випадках, коли це стає проблемою у вашому коді, ви можете більш легко зрозуміти цю проблему і, таким чином, не доведеться витрачати час на розбиття вашого коду на пошук. і зрозуміти цю проблему.

Не завжди встановлюється undefined

Один з аспектів Javascript, який важливо розглянути, - це поліморфізм. Поліморфізм полягає в тому, що присвоюючи ті самі типи змінних / слотів у об'єкті, як показано нижче.

var foo = "str";
foo = 100;          // variable foo is now labeled polymorphic by the browser
var bar = ["Some", "example"];
bar[2] = "text";    // bar is a monomorphic array here because all its entries have the
                    // same type: string primitive
bar[1] = undefined; // bar is now a polymorphic array

Однак існують дві основні неспростовні проблеми з поліморфними масивами:

  1. Вони повільні і пам'ять неефективні. При доступі до певного індексу, замість того, щоб просто отримати глобальний тип для масиву, замість цього браузер повинен отримати тип за індексом, згідно з яким кожен індекс зберігає додаткові метадані його типу.
  2. Поліморфний, завжди поліморфний. Коли масив стає поліморфним, поліморфізм не може бути скасований у браузерах Webkit. Таким чином, навіть якщо ви відновите поліморфний масив як не-поліморфний, воно все одно зберігатиметься браузером як поліморфний масив.

Можна уподібнити поліморфізм до наркозалежності. На перший погляд це здається надзвичайно прибутковим: гарний досить пухнастий код. Тоді кодер вводить їх масив в препарат поліморфізму. Миттєво поліморфний масив стає менш ефективним, і він ніколи не може стати настільки ж ефективним, як це було раніше, поки він не вживається наркотиками. Щоб співвіднести цю обставину з реальним життям, хтось із кокаїну може навіть не вміти керувати простим дверним ручкою, тим більше зможе розрахувати цифри PI. Аналогічно, масив на препарат поліморфізму не може бути таким же ефективним, як мономорфний масив.

Але, як аналогія наркотичних подорожей відноситься до delete операція Відповідь належить до останнього рядка коду в наведеному вище фрагменті. Таким чином, нехай він буде переглянутий, на цей раз з твіст.

var bar = ["Some", "example"];
bar[2] = "text";    // bar is not a polymorphic array here because all its entries have the
                    // same type: string primitive
bar[1] = "";        // bar is still a monomorphic array
bar[1] = undefined; // bar is now a polymorphic array

Спостерігайте. bar[1] = "" не примушує поліморфізму в той час як bar[1] = undefined робить Тому завжди слід, коли це можливо, використовувати відповідний тип для своїх об'єктів, щоб не випадково викликати поліморфізм. Одна така особа може використовувати наступний список як загальне посилання, щоб отримати їх. Однак, будь ласка, не використовуйте явно нижчі ідеї. Замість цього використовуйте будь-що, що добре працює для вашого коду.

  • Використовуючи масив / змінну, набрану до логічного примітиву, використовуйте either false або undefined як порожнє значення. Уникаючи непотрібного поліморфізму, це добре, переписування всього коду явно забороняє, ймовірно, фактично призведе до зниження продуктивності. Використовуйте загальне судження!
  • Використовуючи масив / змінну, набрану до числа примітиву, використовуйте 0 як порожнє значення. Зверніть увагу, що внутрішньо існує два типи чисел: швидкі цілі числа (від 2147483647 до -2147483648 включно) і повільна плаваюча точка удвічі (щось інше, ніж це, в тому числі NaN і Infinity) Коли ціле число знижується до подвійного, його не можна повернути до цілого числа.
  • Використовуючи масив / змінну, набрану рядком примітиву, використовуйте "" як порожнє значення.
  • При використанні символу, почекайте, чому ви використовуєте символ?!?! Символи погані для виконання. Все, що запрограмоване для використання символів, можна перепрограмувати, щоб не використовувати символи, в результаті чого швидший код без символів. Символи дійсно просто неефективні мета-цукру.
  • Використовуючи щось інше, використовуйте null.

Проте пам'ятайте! Не раптово починайте робити це з усім існуючим вами кодом, оскільки це, ймовірно, порушить такий існуючий код і / або вводить дивні помилки. Швидше за все, така ефективна практика повинна бути реалізована з самого початку, а при перетворенні існуючого коду рекомендується перевірити всі рядки, пов'язані з цим, як подвійний, потрійний, чотирикратний, так як намагання оновити старий код до цієї нової практики може бути таким самим ризикований, оскільки воно нагороджує.


705
2018-02-12 17:48



властивість присвоюється невизначеному, все ще є властивістю об'єкта, тому його не буде видалено GC, якщо не буде прочитано ваш останній абзац. - Lance
Я помилявся торкнутися теми ГК тут. Обидва методи мають однаковий результат для GC: вони видаляють значення, пов'язані з ключем. Якщо це значення було останньою посиланням на якийсь інший об'єкт, цей об'єкт буде очищений. - Dan
властивість присвоюється невизначеною, все ще є властивістю об'єкта, тому його не буде видалено GC GC нічого не влаштовує про властивості. Він збирає та видаляє значення. Поки ніщо не посилається на значення (об'єкт, рядок тощо), GC видаляє його з пам'яті. - meandre
До речі, це подвійна проблема для перевірки наявності властивості об'єкта Javascript. Використовуючи в Оператор надійний, але повільний. Перевірте, чи немає властивості невизначено "це не правильна відповідь", але це шлях швидше. перевірити - rdllopes
Чи відповідає ця відповідь? jsperf в даний час вниз, але цей еталон здається, показує, що різниця швидкості складає лише 25%, що ніде закрити до "~ 100 разів повільніше" у цьому відповіді. - Cerbrus


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

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

Це працює в Firefox та Internet Explorer, і я думаю, що він працює у всіх інших.


193
2017-10-16 11:03



Чи є спосіб видалити кілька властивостей з одного масиву за допомогою одного виразу - Aakriti.G
Якщо ви намагаєтесь одночасно видалити кілька властивостей, чи було б краще просто перейти на новий об'єкт? - jasonscript


Оновлення 2018-07-21: Довгий час я відчував себе збентеженим щодо цієї відповіді, тому я думаю, що прийшов час трохи помацати його. Просто трохи коментарів, роз'яснень та форматування, щоб допомогти прискорити читання необгрунтовано довгих і заплутаних частин цієї відповіді.


КОРОТКА ВЕРСІЯ

Фактична відповідь на питання

Як інші сказали, ви можете використовувати delete.

obj // {"foo": "bar"}
delete obj["foo"]
obj // {}
obj["foo"] // undefined

Масив еквівалент

Не треба delete з масиву Використовуйте Array.prototype.splice замість цього.

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

ДОВГА ВЕРСІЯ

JavaScript є OOP Language, тому все є об'єктом, у тому числі масиви. Таким чином, я вважаю, що необхідно вказати на певне застереження.

У масивах, на відміну від простих старих об'єктів, використовується delete залишає сміття у формі null, створюючи "дірку" в масиві.

var array = [1, 2, 3, 4];
delete array[2];
/* Expected result --> [1, 2, 4]
 * Actual result   --> [1, 2, null, 4]
 */

Як ви можете бачити, delete не завжди працює, як можна було б очікувати. Значення перезаписується, але пам'ять не перерозподіляється. Тобто, array[4] не переміщено до array[3]. Що на відміну від Array.prototype.unshift, який вставляє елемент у початок масиву і зміщує все (array[0] стає array[1]і т. д.)

Чесно кажучи, крім встановлення на null а не undefined- який легітимно дивний - це поведінка не слід будьте здивовані, оскільки delete є універсальним оператором, наприклад typeof, це важко кипить на мову і не повинно турбуватися про це тип об'єкта, на якому він використовується, в той час як Array є підкласом Object методами спеціально розроблений для робота з масивами. Тому для цього немає підстав deleteмати спеціальний випадок, приготований для перестановки масиву, так як це просто сповільнить роботу з непотрібною роботою. У ретроспективі мої очікування були нереалістичними.

Звичайно, це зробив здивуй мене. Тому що я написав це, щоб виправдати мій хрестовий похід проти "нульової сміття":

Ігнорування небезпек і проблем, властивих null, а простір витрачається, це може бути проблематично, якщо масив повинен бути точним.

Який страшний виправдання для того, щоб позбутися nullс--null це небезпечно, якщо воно використовується неналежним чином, і воно не має нічого спільного з "точністю". Справжньою причиною не слід delete з масиву, тому що залишення сміттєвих і грязних структур даних є незрозумілими та схильними до помилок.

Далі йдеться про придурений сценарій, який стає досить довгим, тому ви можете перейти до розділу, Рішення, якщо хочете. Єдина причина, через яку я залишаю цей розділ, полягає в тому, що я думаю, що деякі люди напевно думають, що це смішно, і я не хочу бути "тим хлопцем", який публікує "смішну" відповідь, а потім видаляє все "смішно" з нього пізніше .

... Це дурень, я знаю.

Складений і довгостроковий сценарій PDP-11

Наприклад, скажімо, ви створюєте веб-програму, яка використовує JSON-серіалізацію для зберігання масиву, який використовується для "вкладок" у рядку (у цьому випадку localStorage) Давайте також скажемо, що код використовує числові показники членів масиву для "заголовка" їх при нанесенні на екран. Чому ви робите це, а не просто зберігаєте "титул", а? Оскільки... причин.

Гаразд, давайте просто скажемо, що ви намагаєтесь заощадити пам'ять на прохання цього один користувач, який запускає мікрокомп'ютер PDP-11 з 1960-х років під управлінням UNIX, і написав свій власний браузер із підтримкою JavaScript, сумісний з JavaScript, оскільки X11 поза питанням.

Все більше дурний краєвид сценарію в бік, використовуючи delete на вказаний масив призведе до null забруднюючи масив і, ймовірно, викликаючи помилки в додатку пізніше. І якщо ви перевіряєте null, це було б прямим пропуском числа, що призвело до того, що вкладки виглядали як [1] [2] [4] [5] ....

if (array[index] == null)
    continue;
else
    title = (index + 1).toString();
/* 0 -> "1"
 * 1 -> "2"
 * 2 -> (nothing)
 * 3 -> "4"
 */

Так, це точно не те, що ти хотів.

Тепер ти міг тримати другий ітератор, як j, збільшувати лише тоді, коли дійсні значення будуть прочитані з масиву. Але це точно не вирішить null випуск, і вам все одно доведеться порадувати це тролль PDP-11 користувач. На жаль, його комп'ютер просто не робить мати достатньо пам'яті, щоб провести це останнє ціле число (не питайте, як йому вдається обробляти масив змінної ширини ...).

Отже, він надсилає вам електронний лист у гніві:

Hey, your webapp broke my browser! I checked my localStorage database after your stupid code made my browser segfault, and this is what I found:

>"tabs:['Hello World', 'foo bar baz', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ... ]"

After clearing my precious data, it segfaulted again, and I did a backtrace, and what do I find? WHAT DO I FIND!? YOU USE TOO MANY VARIABLES!

>var i = index;
>var j = 1;

Grr, I am angry now.
-Troll Davidson

Проте тепер ти закінчуєшся з розумом. Цей хлопець скаржиться на безперебійну роботу свого додатка, і ви хочете сказати, щоб він зачинився і пішов на кращий комп'ютер.

Рішення: Array.prototype.splice

На щастя, масиви робити мати спеціальний метод для видалення індексів та перерозподілу пам'яті: Array.prototype.splice(). Ви можете написати щось на зразок цього:

Array.prototype.remove = function(index){
  this.splice(index,1);
}
...
array = [1, 2, 3, 4];
array.remove(2);
// Result -> [1, 2, 4]

І просто так, ви задоволені паном PDP-11. Ура! (Я все ще скажу йому, хоча ...)

Array.prototype.splice vs. Array.prototype.slice

Я відчуваю, що важливо вказати на різницю між цими двома однаково названими функціями, оскільки вони дуже корисні.

Array.prototype.splice (початок, n)

.splice() мутувати масив і повертає видалені індекси. Масив нарізаний починаючи з індексу, start, і n елементи нарізані. Якщо n не вказано, весь масив після start викреслений (n = array.length - start)

let a = [5,4,3,2,1];
let chunk = a.splice(2,2);

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

chunk; // [3,2]
a;     // [5,4,1]

Array.prototype.slice (початок, кінець)

.slice() є неруйнуючим і повертає новий масив з вказаними індексами з start до end. Якщо end залишається невизначеною, поведінка така ж, як і .splice() (end = array.length) Поведінка є дещо складною, оскільки з якоїсь причини end індекси з 1 замість 0. Я не знаю, чому це робиться, але це так. Крім того, якщо end <= start, результат - порожній масив.

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

// a             [5,4,3,2,1]
// start          0 1 2 - -
// end, for...    - - - - -
//   chunks[0]  0 - - - - -   
//   chunks[1]    1 2 - - -
//   chunks[2]    1 2 3 - -
//   chunks[3]    1 2 3 4 5

chunks; // [ [], [], [3], [3,2,1] ]
a;      // [5,4,3,2,1]

Насправді це не те, що відбувається, але це простіше думати про це. За словами MDN, ось що відбувається насправді:

// a             [5,4,3,2,1]
// start          0 1 2 - - -
// end, for...    - - - - - -
//   chunks[0]    0 - - - - -
//   chunks[1]    0 1 2 - - -
//   chunks[2]    0 1(2)3 - -
//   chunks[3]    0 1(2 3 4)5

Індекс вказаний end просто виключено з скибочки. Індекси в скобках вказують на те, що отримують нарізання. У будь-якому випадку поведінка не є інтуїтивно зрозумілою, і вона повинна спричинити справедливу частку окремих помилок, отже вам може бути корисним зробити функцію обгортки більш точно наслідувати поведінці .splice():

function ez_slice(array, start = 0, n = null){
    if(!Array.isArray(array) || !is_number(start))
        return null;

    if(is_number(n))
        return array.slice(start, start + n);

    if(n === null)
        return array.slice(start);

    return null;
}

ez_slice([5,4,3,2,1], 2, 1) // [3]
ez_slice([5,4,3,2,1], 2)    // [3,2,1]

/* Fun fact: isNaN is unreliable.
 * [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(isNaN)
 * [NaN, {}, undefined, "Hi"]
 *
 * What we want is...
 *
 * [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(is_nan)
 * [NaN]
 */
function is_nan(num){
    return typeof num === "number"
        && num !== num;
}

function is_number(num){
    return !is_nan(num)
        && typeof num === "number"
        && isFinite(num);
}

Зауважте, що функція обгортки розроблена так, щоб бути дуже суворою щодо типів, і повернеться null якщо щось відключено Це включає в себе введення рядка, як "3". Програмісту залишається старанним про його типи. Це заохочує хорошу практику програмування.

Оновлення відносно is_array()

Це стосується цього фрагмента (тепер видаленого):

function is_array(array){
    return array !== null
        && typeof array === "object"
        && typeof array.length !== "undefined"
        && array.__proto__ === Array.prototype;
}

Як виявляється, насправді є вбудований спосіб визначити, чи масив дійсно масив, і це є Array.isArray(), представлений в ECMAScript 5 (грудень 2009 р.). Я знайшов це, дивлячись, чи було запитання про те, як розповісти масиви про об'єкти, щоб побачити, чи існує краще рішення, ніж моє, чи додати мій, якщо цього не було. Отже, якщо ви використовуєте версію JavaScript, яка раніше, ніж ECMA 5, є ваша поліфіль. Однак я настійно рекомендую не використовувати мою is_array() функція, оскільки продовження підтримки старих версій JavaScript означає продовження підтримки старих веб-переглядачів, що їх реалізують, що означає заохочення використання незахищеного програмного забезпечення та потрапляння користувачів на небезпеку для шкідливих програм. Так, будь ласка, користуйтеся Array.isArray(). Використовуйте let і const. Використовуйте нові функції, які додаються до мови. Не треба використовувати префікси постачальника. Видалити що IE поліфіль чіпати з вашого веб-сайту. Видалити це XHTML <!CDATA[[... Також - ми перейшли до HTML5 у 2014 році. Чим швидше кожний відкликає підтримку цих старих / езотеричних браузерів, тим швидше постачальники браузера насправді дотримуються стандарту Інтернету та охоплюють нову технологію, і чим швидше ми зможемо перейти до більш безпечна мережа.


134
2017-09-18 00:56



Це delete Ключове слово, однак, набагато зручніше, LOL - Braden Best
Цей підхід не змінює оригінальний об'єкт, який все ще може бути посиланням в іншому місці. Це може або не може бути проблемою в залежності від того, як вона використовується, але це те, що слід пам'ятати. - Tamas Czinege
@ B1KMusic Ось спосіб видалення елемента з масиву: сплайсинг - wulftone
@wulftone nope, що розбиває масив і не робить нічого, щоб видалити значення. Я дійсно думаю, що найкращим способом видалення з масиву, де потрібні певні значення для видалення, є використання delete і створіть функцію збирання сміття для її очищення. - Braden Best
Я не бачу splice в редакції, але remove повинно бути Array.prototype.remove = function(index) { this.splice(index, 1); }; - Ry-♦


Старе питання, сучасна відповідь. Використовуючи руйнування об'єкта, a ECMAScript 6 функція, це так просто, як:

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

Або із запитанням питань:

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

Ви можете бачити це в дії в редакторі спроби Бабель.


Редагувати:

Для перепризначення тієї ж змінної використовуйте a let:

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

92
2017-11-08 18:02



Можливо, тому що метою є видалення властивості з об'єкта, а не створення нового, що не має властивості ... хоча ваше рішення є моїм улюбленим, тому що я віддаю перевагу незмінному шляху. - Vingt_centimes
Питання було сказано "в кінцевому підсумку" новий myObject ". - Koen.
Відповідно до kangax.github.io/compat-table/esnext, властивості об'єкта відпочинку не завершені для ES6, мають нульові реалізації браузера, і лише Babel надає підтримку. - Justin C
Це насправді солодкий один вкладиш для призначення нового об'єкта без небажаних реквізитів, і вже підтримується Node.js 8. * / 9. * з --harmony: node.green /... - Damaged Organic
Це має бути прийнята відповідь в 2018 році :) - Yulian


Іншою альтернативою є використання Underscore.js бібліотека

Зауважте, що _.pick() і _.omit() обидва повертають копію об'єкта і безпосередньо не змінюють вихідний об'єкт. Присвоєння результату оригінальному об'єкту повинно робити трюк (не показано).

Довідка: посилання  _.pick (об'єкт, ключі *)

Повернути копію об'єкта, відфільтрувати, щоб мати лише значення для ключі з білим списком (або масив дійсних ключів).

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

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

Довідка: посилання  _.omit (об'єкт, ключі *)

Повертайте копію об'єкта, фільтруючи, щоб опустити чорний список клавіш (або масив ключів).

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

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

Для масивів _.filter() і _.reject() може бути використаний аналогічним чином.


67
2018-05-24 18:53



Пам'ятайте, що якщо клавішами вашого об'єкта є номери, вам може знадобитися _.omit(collection, key.toString()) - Jordan Arseno
Чому ви посилались на Вікіпедію, а не на underscorejs.org? - E730
@ E730 Хороше запитання. Я не знаю, чому один з редакторів змінив його, щоб вказати на wikipedia.org / wiki / Underscore.js. Я повернувся до underscorejs.org. - Thaddeus Albers
Хммммм .... Підкреслити ~ 100x повільніше, ніж delete obj[prop] що ~ 100x повільніше ніж obj[prop] = undefined. - Jack Giffin


Термін, який ви використали у вашому заголовку питання Remove a property from a JavaScript object, можна тлумачити по-різному. Потрібно видалити його для всієї пам'яті, а список клавіш об'єктів або інший - просто видалити його з об'єкта. Як це було згадано в деяких інших відповідях, delete ключове слово є основною частиною. Скажімо, у вас є ваш об'єкт:

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

Якщо ти зробиш:

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

результат буде:

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

Ви можете видалити цю конкретну клавішу з ключів вашого об'єкта, таких як:

delete myJSONObject["regex"];

Потім використовуйте ключові слова Object.keys(myJSONObject) був би:

["ircEvent", "method"]

Але справа в тому, якщо ви дбаєте про пам'ять і хочете, щоб весь об'єкт був видалений з пам'яті, рекомендується встановити його на нуль, перш ніж видалити ключ:

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

Інший важливий момент полягає в тому, щоб бути обережним щодо інших посилань на той самий об'єкт. Наприклад, якщо ви створюєте таку змінну:

var regex = myJSONObject["regex"];

Або додайте його як новий покажчик на інший об'єкт, наприклад:

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

Тоді, навіть якщо ви видалите його з об'єкта myJSONObject, що конкретний об'єкт не буде видалено з пам'яті, оскільки regex змінна і myOtherObject["regex"] досі мають свої цінності. Тоді як ми могли б видалити об'єкт із пам'яті напевно?

Відповідь буде видаліть всі посилання, які ви маєте у своєму коді, вказали на цей самий об'єкт а також не використовувати var твердження для створення нових посилань на цей об'єкт. Це остання точка зору var заяви є одним з найважливіших проблем, з якими ми стикаємося, оскільки їх використання var заяви заважають створенню об'єкта отримати видалення.

Це означає, що у цьому випадку ви не зможете видалити цей об'єкт, оскільки ви створили regex змінна через a var виписка, а якщо ви робите:

delete regex; //False

Результат буде false, що означає, що ваше твердження видалення не було виконано, як ви очікували. Але якщо ви ще не створили цю змінну раніше, а ти тільки мав myOtherObject["regex"] як ваш останній існуючий довідник, ви могли б зробити це просто, видаливши його, як:

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

Іншими словами, об'єкт JavaScript забирається, як тільки в коді не вказано посилання на цей об'єкт.


Оновлення: Завдяки @AgentME:

Встановлення властивості до нуля перед видаленням не виконується   що-небудь (якщо об'єкт не був запечатаний Object.seal і   видалити не вдається Це звичайно не так, як тільки ви спеціально   спробуйте)

Щоб отримати більше інформації про Object.seal: Object.seal ()


34
2018-02-12 06:29



Ви помиляєтесь - лише посилання на об'єкти передаються в JavaScript, так що якщо myJSONObject.regexЗначення 's - це рядок, і ви призначаєте його іншому об'єкту, інший об'єкт має копію цього значення. - Michał Perłakowski
Ви маєте рацію, і це цитата: "будьте обережні щодо ваших інших посилань на той самий об'єкт". - Mehran Hatami


Припустимо, у вас є об'єкт, який виглядає так:

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

Видалення властивості об'єкта

Якщо ви хочете використовувати весь staff масив, правильний спосіб зробити це, буде зробити це:

delete Hogwarts.staff;

Крім того, ви можете це зробити:

delete Hogwarts['staff'];

Аналогічним чином, видалення всього масиву студентів буде здійснено шляхом дзвінка delete Hogwarts.students; або delete Hogwarts['students'];.

Видалення індексу масиву

Тепер, якщо ви хочете видалити одного співробітника або студента, процедура трохи відрізняється, тому що обидва властивості є самими масивами.

Якщо ви знаєте індекс вашого співробітника, ви можете просто зробити це:

Hogwarts.staff.splice(3, 1);

Якщо ви не знаєте індекс, вам також доведеться виконувати пошук індексу:

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

Примітка

Поки ви технічно можете використовувати delete для масиву, використовуючи це призводить, наприклад, до отримання неправильних результатів Hogwarts.staff.length в подальшому. Іншими словами, delete буде видалити елемент, але воно не оновить значення length власність Використовуючи delete також буде перешкоджати вашій індексації.

Отже, при видаленні значень з об'єкта, спочатку слід враховувати, чи маєте ви справу з властивостями об'єкта, чи ви маєте справу з значеннями масиву, і вибираєте відповідну стратегію на основі цього.

Якщо ви хочете поекспериментувати з цим, ви можете використовувати це скрипка як вихідна точка.


30
2018-02-21 18:09



Я думаю, ви повинні завжди використовувати splice на масиві замість delete. - Joel Trauger
@JoelTrauger: ось що я кажу ;-) - John Slegers
Так. Мій коментар у тому, що delete Не повинно навіть бути справою. Його splice це те, що ОП шукав. - Joel Trauger
@JoelTrauger: Як я намагався пояснити, delete слід використовувати для властивостей об'єкта та splice для елементів масиву. - John Slegers
Спліс дійсно повільний. Хоча його слід використовувати замість delete на масивах, було б розумніше не створювати код, орієнтований навколо нього взагалі. - Jack Giffin


ECMAScript 2015 (або ES6) постачається з вбудованим Відобразити об'єкт Ви можете видалити об'єкт об'єкта, викликаючи його Reflect.deleteProperty () функція з цільовим об'єктом та ключем властивості як параметри:

Reflect.deleteProperty(myJSONObject, 'regex');

що еквівалентно:

delete myJSONObject['regex'];

Але якщо властивість об'єкта не налаштовується, його не можна видалити ні за допомогою функції deleteProperty, ні видалити оператора:

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

Object.freeze () робить всі властивості об'єкта не налаштовуваними (крім інших речей). deleteProperty функція (а також видалити оператор) повертає false коли намагається видалити будь-які його властивості. Якщо властивість налаштовується, вона повертається true, навіть якщо майна не існує.

Різниця між delete і deleteProperty це при використанні строгого режиму:

"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

29
2018-01-10 16:36



@ Готдо це має більше переваг, особливо коли вам потрібно зробити деякі функціональні речі. Наприклад, ви можете призначити функцію для змінної, передавати як аргумент або використовувати apply, call, bind функції ... - madox2