Как удалить свойство из объекта JavaScript?

Скажем, я создаю объект следующим образом:

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

Каков наилучший способ удалить свойство regex, чтобы в итоге получить новый myObject следующим образом:

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI"
};
+5722
источник поделиться
43 ответа
  • 1
  • 2

Вот так:

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

Demo

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

console.log(myObject);

Для всех, кто интересуется большей информацией об этом, пользователь Qaru kangax написал невероятно подробное сообщение в блоге о заявлении delete в своем блоге, Понимание удаления. Настоятельно рекомендуется.

+7820
источник

delete оператора неожиданно замедляется!

Посмотрите на бенчмарк.

Удалить - единственный верный способ удалить свойства объекта без каких-либо остатков, но он работает ~ в 100 раз медленнее, по сравнению с его "альтернативным", устанавливающим object[key] = undefined.

Эта альтернатива не является правильным ответом на этот вопрос! Но, если вы используете его с осторожностью, вы можете значительно ускорить некоторые алгоритмы. Если вы используете delete в циклах, и у вас проблемы с производительностью, прочитайте подробное объяснение.

Когда следует использовать delete и когда заданное значение undefined?

Объект может рассматриваться как набор пар ключ-значение. То, что я называю "значением", является примитивным или ссылкой на другой объект, связанный с этим "ключом".

Используйте delete , когда вы передаете объект результата в код, на котором у вас нет контроля (или когда вы не уверены в своей команде или себе).

Он удаляет ключ из хэш-карты.

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

Если вы не уверены в производительности, используйте параметр undefined. Это может серьезно повлиять на ваш код.

Ключ остается на своем месте в hashmap, только значение заменяется undefined. Поймите, что for..in цикл все равно будет перебирать этот ключ.

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

Используя этот метод, не все способы определения свойства существования будут работать, как ожидалось.

Однако этот код:

object.field === undefined

будут вести себя эквивалентно для обоих методов.

тесты

Подводя итог, существуют различия в способах определения существования свойства и for..in цикла 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\ 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 делает. Поэтому всегда следует, когда это возможно, использовать соответствующий тип для своих объектов, чтобы случайно не вызвать полиморфизм. Один из таких лиц может использовать следующий список в качестве общей ссылки, чтобы получить их. Однако, пожалуйста, не используйте явно указанные ниже идеи. Вместо этого используйте все, что хорошо работает для вашего кода.

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

Однако будьте внимательны! Не начинайте делать это со всем существующим кодом, поскольку он, скорее всего, сломает такой существующий код и/или представит странные ошибки. Скорее, такая эффективная практика должна быть реализована с самого начала, а при преобразовании существующего кода рекомендуется дважды, тройная, четырехкратная проверка всех строк, относящихся к этому, как попытка обновить старый код до этой новой практики, может быть как рискованно, так как это полезно.

+859
источник

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

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

Это работает в Firefox и Internet Explorer, и я думаю, что это работает во всех остальных.

+228
источник

Обновление 2018-07-21: В течение долгого времени мне было стыдно за этот ответ, поэтому я думаю, что пришло время немного его подправить. Просто небольшой комментарий, уточнение и форматирование, чтобы помочь ускорить чтение излишне длинных и запутанных частей этого ответа.


КРАТКАЯ ВЕРСИЯ

Актуальный ответ на вопрос

Как уже говорили другие, вы можете использовать delete.

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

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

Не delete из массива. Array.prototype.splice этого используйте Array.prototype.splice.

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

Длинная версия

JavaScript - это язык ООП, поэтому все является объектом, включая массивы. Таким образом, я считаю необходимым указать конкретную оговорку.

В массивах, в отличие от простых старых объектов, использование 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 --which законно странно - такое поведение не должно удивлять, так как delete является унарным оператором, как typeof, что вкрутую на язык и не должен заботиться о типе объекта, на котором он используется, тогда как Array является подклассом Object с методами, специально разработанными для работы с массивами. Таким образом, для delete нет веских оснований для того, чтобы подготовить специальный случай для повторного смещения массива, поскольку это просто замедлит работу с ненужной работой. Оглядываясь назад, мои ожидания были нереальными.

Конечно, это меня удивило. Потому что я написал это, чтобы оправдать свой крестовый поход против "нулевого мусора":

Игнорирование опасностей и проблем, присущих null, и потерянного пространства, это может быть проблематично, если массив должен быть точным.

Что является ужасным оправданием для того, чтобы избавиться от null s-- null опасен только при неправильном использовании и не имеет ничего общего с "точностью". Реальная причина, по которой вы не должны delete из массива, заключается в том, что оставление заполненных мусором и грязных структур данных является небрежным и подверженным ошибкам.

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

... это глупо, я знаю.

Придуманный и затянувшийся сценарий PDP-11

Например, допустим, вы создаете веб-приложение, которое использует JSON-сериализацию для хранения массива, используемого для "вкладок" в строке (в данном случае localStorage). Допустим также, что код использует числовые индексы элементов массива для "заголовка" их при рисовании на экране. Почему вы делаете это, а не просто сохраняете "заголовок"? Потому что... причины.

Ладно, давайте просто скажем, что вы пытаетесь сэкономить память по запросу этого пользователя, который запускает мини-компьютер PDP-11 из 1960-х под управлением UNIX и написал свой собственный браузер на основе Elinks, совместимый с 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 (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(), поведение аналогично .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, то ваш polyfill. Однако я настоятельно рекомендую не использовать мою is_array(), поскольку продолжать поддерживать старые версии JavaScript означает продолжать поддерживать старые браузеры, которые их реализуют, что означает поощрение использования небезопасного программного обеспечения и подвергание пользователей риску вредоносного ПО. Поэтому, пожалуйста, используйте Array.isArray(). Используйте let и const. Используйте новые функции, которые добавляются в язык. Не используйте префиксы поставщиков. Удалите это дерьмо IE polyfill с вашего сайта. Удалите этот XHTML <!CDATA[[... дерьмо тоже] - мы перешли на HTML5 еще в 2014 году. Чем раньше все откажутся от поддержки этих старых/эзотерических браузеров, тем скорее производители браузеров действительно будут следовать веб-стандарту и принять новые технологии, и чем раньше мы сможем перейти к более безопасной сети.

+194
источник

Старый вопрос, современный ответ. Используя деструктурирование объектов, 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);

Вы можете увидеть его в действии в редакторе Babel try-out.


Edit:

Чтобы переназначить одну и ту же переменную, используйте let:

let myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
({ regex, ...myObject } = myObject);
console.log(myObject);
+159
источник

Другой альтернативой является использование библиотеки 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() могут использоваться аналогичным образом.

+89
источник

Синтаксис распространения (ES6)

Для тех, кто нуждается в этом...

Чтобы завершить ответ @Koen в этой теме, на случай, если вы захотите удалить динамическую переменную с использованием синтаксиса распространения, вы можете сделать это следующим образом:

const key = 'a';

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

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

* foo будет новой переменной со значением a (которое равно 1).


ОБНОВЛЕНИЕ:
Существует несколько распространенных способов удаления свойства из объекта.
У каждого есть свои плюсы и минусы (проверьте это сравнение производительности):

Оператор удаления
Однако, если вы работаете с большим количеством объектов, это может быть не лучшим выбором, поскольку его производительность не оптимизирована.

delete obj[key];


Перераспределение
Более чем в 2 раза быстрее, чем delete, однако свойство не удаляется и может быть повторено.

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


Оператор распространения
Этот оператор ES6 позволяет нам возвращать совершенно новый объект, исключая любые свойства, не изменяя существующий объект. Недостатком является то, что он имеет худшую производительность из вышеперечисленных и не рекомендуется использовать, когда вам нужно удалить много свойств одновременно.

{ [key]: val, ...rest } = obj;
+67
источник

Термин, который вы использовали в заголовке вопроса 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"]

Но дело в том, что если вы заботитесь о памяти и хотите, чтобы весь объект удалялся из памяти, рекомендуется установить его значение null до удаления ключа:

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

Другим важным моментом здесь является осторожность в отношении других ссылок на один и тот же объект. Например, если вы создаете переменную типа:

var regex = myJSONObject["regex"];

Или добавьте его как новый указатель на другой объект, например:

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

Тогда даже если вы удалите его из своего объекта myJSONObject, этот конкретный объект не будет удален из памяти, так как переменная regex и myOtherObject["regex"] все еще имеют свои значения. Тогда как мы могли бы точно удалить объект из памяти?

Ответ будет удалить все ссылки, которые у вас есть в вашем коде, указал на тот самый объект, а также не использовать var для создания новых ссылок на этот объект. Этот последний пункт в отношении операторов var является одной из наиболее важных проблем, с которыми мы обычно сталкиваемся, поскольку использование операторов var предотвратит удаление объекта, созданного.

Это означает, что в этом случае вы не сможете удалить этот объект, потому что вы создали переменную regex с помощью инструкции var, и если вы это сделаете:

delete regex; //False

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

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

Другими словами, объект JavaScript будет убит, как только в коде не будет указана ссылка на этот объект.


Update: Благодаря @AgentME:

Установка свойства null перед удалением не выполняется ничего (если объект не был закрыт объектом Object.seal и удаление не выполняется. Это обычно не так, если вы специально попробовать).

Чтобы получить дополнительную информацию по Object.seal: Object.seal()

+45
источник

ECMAScript 2015 (или ES6) поставляется со встроенным Reflect объектом. Свойства объекта можно удалить, вызвав функцию 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
+38
источник

Предположим, что у вас есть объект, который выглядит так:

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 также испортило бы вашу индексацию.

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

Если вы хотите поэкспериментировать с этим, вы можете использовать этот скрипт в качестве отправной точки.

+37
источник

Используя ES6:

(Разрушение + Оператор распространения)

const myObject = {
    regex: "^http://.*",
    b: 2,
    c: 3
};
const { regex, ...noRegex } = myObject;
console.log(noRegex); // => { b: 2, c: 3 }
+29
источник

удалить оператор - лучший способ сделать это.

Живой пример для показа:

var foo = {bar: 'bar'};
delete foo.bar;
console.log('bar' in foo); // Logs false, because bar was deleted from foo.
+27
источник

Я лично использую Underscore.js или Lodash для манипулирования объектами и массивами:

myObject = _.omit(myObject, 'regex');
+27
источник

Использование метода удаления - лучший способ сделать это, согласно описанию MDN, оператор удаления удаляет свойство из объекта. Так что вы можете просто написать:

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

Оператор удаления удаляет данное свойство из объекта. При успешном удалении он вернет true, иначе будет возвращено false. Однако важно учитывать следующие сценарии:

  • Если свойство, которое вы пытаетесь удалить, не существует, удаление не будет иметь никакого эффекта и вернет true

  • Если в цепочке прототипов объекта существует свойство с таким же именем, то после удаления объект будет использовать свойство из цепочки прототипов (другими словами, удаление влияет только на собственные свойства).

  • Любое свойство, объявленное с помощью var, не может быть удалено из глобальной области или из области функции.

  • Таким образом, delete не может удалять какие-либо функции в глобальной области видимости (будь то часть из определения функции или функция (выражение).

  • Функции, которые являются частью объекта (кроме
    глобальная область) можно удалить с помощью delete.

  • Любое свойство, объявленное с помощью let или const, не может быть удалено из области, в которой они были определены. Ненастраиваемые свойства не могут быть удалены. Это включает в себя свойства встроенных объектов, таких как Math, Array, Object и свойства, которые создаются как неконфигурируемые с помощью методов, таких как Object.defineProperty().

Следующий фрагмент дает еще один простой пример:

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

Для получения дополнительной информации и увидеть больше примеров, перейдите по ссылке ниже:

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

+22
источник

Другое решение, использующее 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);

Однако он будет мутировать исходный объект. Если вы хотите создать новый объект без указанного ключа, просто назначьте функцию сокращения новой переменной, например:

(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);
+20
источник

Чтобы клонировать объект без свойства:

Например:

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

И нам нужно удалить "а".

1. С явным ключом реквизита:

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

2.С переменной переменной ключ:

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

Функция стрелки 3.Cool 😎:

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

object = removePropery('a', object);

4. Для нескольких свойств

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

использование

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

Или же

    const propsToRemove = ['a', 'b']
    object = removeProperties(object, ...propsToRemove) // result => { c: 3 }
+20
источник

Эта статья очень старая, и я считаю ее очень полезной, поэтому я решил поделиться функцией unset, которую я написал, в случае, если кто-то еще увидит это сообщение и подумает, почему это не так просто, как в функции отмены PHP.

Причиной написания этой новой функции unset является сохранение индекса всех других переменных в этой hash_map. Посмотрите на следующий пример и посмотрите, как индекс "test2" не изменился после удаления значения из 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"}
+19
источник

Здесь есть много хороших ответов, но я просто хочу услышать, что при использовании delete для удаления свойства в JavaScript часто бывает полезно сначала проверить, существует ли это свойство для предотвращения ошибок.

например

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

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

Из-за динамического характера JavaScript часто бывают случаи, когда вы просто не знаете, существует ли свойство или нет. Проверка существования obj до && также гарантирует, что вы не выкидываете ошибку из-за вызова функции hasOwnProperty() объекта undefined.

Извините, если это не добавило вашего конкретного варианта использования, но я считаю, что это хороший дизайн для адаптации при управлении объектами и их свойствами.

+18
источник

Используя ramda # dissoc, вы получите новый объект без атрибута regex:

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

Вы также можете использовать другие функции для достижения того же эффекта - опустить, выбрать,...

+14
источник

Попробуйте использовать следующий метод. Назначьте значение свойства Object undefined. Затем stringify объект и parse.

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

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

console.log(myObject);
+13
источник

Если вы хотите удалить свойство, глубоко вложенное в объект, вы можете использовать следующую рекурсивную функцию с указанием пути к свойству в качестве второго аргумента:

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;
    }
};

Пример:

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

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

//Prints {level1: {level2: {}}}
+11
источник

Вы можете просто удалить любое свойство объекта, используя ключевое слово delete.

Например:

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

Чтобы удалить любое свойство, например key1, используйте ключевое слово delete следующим образом:

delete obj.key1

Или вы также можете использовать массивную нотацию:

delete obj[key1]

Ссылка: MDN.

+7
источник

Утверждение Дэна о том, что "удаление" происходит очень медленно, и поставленный в нем тест был усомнился. Поэтому я сам проверил тест в Chrome 59. Кажется, что "delete" примерно в 30 раз медленнее:

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

Обратите внимание, что я специально выполнял несколько операций "удалить" в одном цикле цикла, чтобы минимизировать эффект, вызванный другими операциями.

+6
источник

Object.assign() и 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"];
        }
    }
);
+6
источник

Рассмотрите возможность создания нового объекта без свойства "regex", поскольку исходный объект всегда может ссылаться на другие части вашей программы. Таким образом, вам следует избегать манипулирования им.

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

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

console.log(newMyObject);
+6
источник

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

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

console.log(myObject)
console.log(regex)
console.log(other)
+6
источник

Попробуйте это

delete myObject['key'];
+5
источник

Здравствуйте, Вы можете попробовать этот простой вид

var obj = [];

obj.key1 = {name: "John", room: 1234};
obj.key2 = {name: "Jim", room: 1234};

delete(obj.key1);
+5
источник

Удаление свойства в JavaScript

На этой странице представлено много разных опций не потому, что большинство опций неверны - или потому что ответы являются дубликатами, а потому, что подходящий метод зависит от ситуации, в которой вы находитесь, и целей задач, которые вы и/или вы Команда пытается выполнить. Чтобы ответить на ваш вопрос однозначно, нужно знать:

  1. Версия ECMAScript, на которую вы ориентируетесь
  2. Диапазон типов объектов, для которых вы хотите удалить свойства, и тип имен свойств, которые необходимо пропустить (Только строки? Символы? Слабые ссылки, сопоставленные с произвольными объектами? Все это были типы указателей свойств в JavaScript в течение многих лет )
  3. Этос/паттерны программирования, которые вы и ваша команда используете. Вы предпочитаете функциональные подходы, и мутация в вашей команде - это словесно, или вы используете методы объектно-ориентированных мутаций на Диком Западе?
  4. Вы хотите добиться этого в чистом JavaScript или хотите & можно использовать стороннюю библиотеку?

После того, как на эти четыре запроса дан ответ, по сути, в JavaScript есть четыре категории "удаления свойств", чтобы удовлетворить ваши цели. Они:

Мутативное удаление свойства объекта, небезопасное

Эта категория предназначена для работы с литералами объекта или экземплярами объекта, когда вы хотите сохранить/продолжить использовать исходную ссылку и не используете функциональные принципы без сохранения состояния в вашем коде. Пример синтаксиса в этой категории:

'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

Эта категория является самой старой, простой и понятной. Наиболее широко поддерживаемая категория удаления имущества. Он поддерживает Symbol & Индексы массива в дополнение к строкам и работают во всех версиях JavaScript, кроме самого первого выпуска. Тем не менее, это мутация, которая нарушает некоторые принципы программирования и влияет на производительность. Это также может привести к неперехваченным исключениям при использовании ненастраиваемых свойств в строгом режиме.

Пропуск свойства строки на основе покоя

Эта категория предназначена для работы с обычными объектами или массивами в более новых разновидностях ECMAScript, когда требуется немутативный подход и вам не нужно учитывать ключи Symbol:

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

Безопасное удаление свойства объекта

Эта категория предназначена для работы с литералами объекта или экземплярами объекта, когда вы хотите сохранить/продолжить использовать исходную ссылку, защищая от исключений, возникающих в неконфигурируемых свойствах:

'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

Кроме того, хотя изменяющиеся объекты на месте не являются объектами без сохранения состояния, вы можете использовать функциональную природу Reflect.deleteProperty для частичного применения и других функциональных методов, которые невозможны с помощью операторов delete.

Пропуск свойства строки на основе синтаксиса

Эта категория предназначена для работы с обычными объектами или массивами в более новых разновидностях ECMAScript, когда требуется немутативный подход и вам не нужно учитывать ключи Symbol:

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

Отсутствие библиотечного имущества

Эта категория обычно обеспечивает большую функциональную гибкость, включая учет символов и символов. опуская более одного свойства в одном утверждении:

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"
+5
источник

Вы можете использовать ES6 деструктурирование с оператором отдыха.

Свойства могут быть удалены с помощью разрушения в сочетании с оператором отдыха. В вашем примере регулярное выражение удалено (игнорируется), а остальные свойства возвращаются как остальные.

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

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

Или вы можете динамически исключать свойства, подобные этим,

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://.*" }
+5
источник
  • 1
  • 2

Посмотрите другие вопросы по меткам или Задайте вопрос