Скажем, я создаю объект следующим образом:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
Каков наилучший способ удалить свойство regex
, чтобы в итоге получить новый myObject
следующим образом:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI"
};
Вот так:
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
в своем блоге, Понимание удаления. Настоятельно рекомендуется.
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
Тем не менее, существуют две основные проблемы, которые невозможно устранить при использовании полиморфных массивов:
Можно уподобить полиморфизм наркотической зависимости. На первый взгляд, это кажется невероятно прибыльным: красивый довольно пушистый код. Затем кодер вводит свой массив в препарат полиморфизма. Мгновенно полиморфная матрица становится менее эффективной, и она никогда не может стать столь же эффективной, как и раньше, с тех пор, как она наркотизирована. Чтобы соотнести такое обстоятельство с реальной жизнью, кто-то из кокаина может даже не иметь возможности управлять простой дверной ручкой, а тем более не в состоянии рассчитать цифры 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
). Когда целое число понижается до двойника, его нельзя отнести к целому числу.""
в качестве пустого значения.null
.Однако будьте внимательны! Не начинайте делать это со всем существующим кодом, поскольку он, скорее всего, сломает такой существующий код и/или представит странные ошибки. Скорее, такая эффективная практика должна быть реализована с самого начала, а при преобразовании существующего кода рекомендуется дважды, тройная, четырехкратная проверка всех строк, относящихся к этому, как попытка обновить старый код до этой новой практики, может быть как рискованно, так как это полезно.
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
delete myObject.regex;
console.log ( myObject.regex); // logs: undefined
Это работает в Firefox и Internet Explorer, и я думаю, что это работает во всех остальных.
Обновление 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
из массива, заключается в том, что оставляя заполненные мусором и грязные структуры данных вокруг, неаккуратно и подвержено ошибкам.
Ниже приведен надуманный сценарий, который становится довольно длинным, поэтому вы можете перейти к разделу "Решение", если хотите. Единственная причина, по которой я покидаю этот раздел, - это то, что я думаю, что некоторые люди, вероятно, считают это забавным, и я не хочу быть "тем парнем", который отправляет "смешной" ответ, а затем удаляет из него все "смешные",
... Это глупо, я знаю.
Например, предположим, что вы создаете webapp, который использует 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
проблему, и вам все равно понравится этот пользовательTrollPDP-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. Ура! (Я бы все же сказал ему, хотя...)
Я считаю важным отметить разницу между этими двумя аналогично названными функциями, поскольку они оба очень полезны.
.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]
.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()
поведения .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[[...
crap, тоже - мы переместились в HTML5 еще в 2014 году.). Чем раньше все откажутся от поддержки этих старых/эзотерических браузеров, тем скорее поставщики браузеров будут действительно следовать веб-стандарту и охватывают новые технологии, и чем скорее мы сможем перейти к более безопасной сети.
delete
, однако, гораздо удобнее, лол
Старый вопрос, современный ответ. Используя деструктурирование объектов, 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);
Другой альтернативой является использование библиотеки 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()
могут использоваться аналогичным образом.
_.omit(collection, key.toString())
delete obj[prop]
что примерно в 100 раз медленнее, чем obj[prop] = undefined
.
Термин, который вы использовали в заголовке вопроса 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()
myJSONObject.regex
является строкой и вы назначаете его какому-либо другому объекту, у другого объекта есть копия этого значения.
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
apply
, call
, bind
functions ...
Предположим, что у вас есть объект, который выглядит так:
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
также испортило бы вашу индексацию.
Таким образом, при удалении значений из объекта всегда сначала учитывайте, имеете ли вы дело с объектами или имеете дело с значениями массива и выбираете на основе соответствующей стратегии.
Если вы хотите поэкспериментировать с этим, вы можете использовать этот скрипт в качестве отправной точки.
splice
в массиве вместо delete
.
Для тех, кто нуждается в этом...
Чтобы завершить ответ @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;
удалить оператор - лучший способ сделать это.
Живой пример для показа:
var foo = {bar: 'bar'};
delete foo.bar;
console.log('bar' in foo); // Logs false, because bar was deleted from foo.
delete
полезно в отношении сборки мусора , оно может быть неожиданно медленным , в немалой степени по той же причине.
Я лично использую Underscore.js или Lodash для манипулирования объектами и массивами:
myObject = _.omit(myObject, 'regex');
Использование метода удаления - лучший способ сделать это, согласно описанию MDN, оператор delete удаляет свойство из объекта. Поэтому вы можете просто написать:
delete myObject.regex;
// OR
delete myObject['regex'];
Оператор delete удаляет заданное свойство из объекта. При успешном удалении оно вернет true, иначе будет возвращено false. Однако важно учитывать следующие сценарии:
Если свойство, которое вы пытаетесь удалить, не существует, delete не будет иметь никакого эффекта и вернет true
Если свойство с тем же именем существует в цепочке прототипов объекта, то после удаления объект будет использовать свойство из цепи прототипа (другими словами, удаление влияет только на собственные свойства).
Любое свойство, объявленное с помощью var, не может быть удалено из глобальной области или из области действия.
Таким образом, delete не может удалить какие-либо функции в глобальной области (независимо от того, является ли это частью определения функции или функции (выражение).
Функции, которые являются частью объекта (кроме
глобальная область действия) можно удалить с помощью удаления.Любое свойство, объявленное с let или const, не может быть удалено из области действия, в которой они были определены. Неконфигурируемые свойства не могут быть удалены. Сюда входят свойства встроенных объектов, таких как Math, Array, Object и свойства, которые создаются как неконфигурируемые с помощью методов Object.defineProperty().
Следующий фрагмент дает еще один простой пример:
var Employee = {
age: 28,
name: 'abc',
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
Другое решение, использующее 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);
Эта статья очень старая, и я считаю ее очень полезной, поэтому я решил поделиться функцией 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"}
Здесь есть много хороших ответов, но я просто хочу услышать, что при использовании delete для удаления свойства в JavaScript часто бывает полезно сначала проверить, существует ли это свойство для предотвращения ошибок.
например
var obj = {"property":"value", "property2":"value"};
if (obj && obj.hasOwnProperty("property2")) {
delete obj.property2;
} else {
//error handling
}
Из-за динамического характера JavaScript часто бывают случаи, когда вы просто не знаете, существует ли свойство или нет. Проверка существования obj до && также гарантирует, что вы не выкидываете ошибку из-за вызова функции hasOwnProperty() объекта undefined.
Извините, если это не добавило вашего конкретного варианта использования, но я считаю, что это хороший дизайн для адаптации при управлении объектами и их свойствами.
Используя ramda # dissoc, вы получите новый объект без атрибута regex
:
const newObject = R.dissoc('regex', myObject);
// newObject !== myObject
Вы также можете использовать другие функции для достижения того же эффекта - опустить, выбрать,...
Попробуйте использовать следующий метод. Назначьте значение свойства Object
undefined
. Затем stringify
объект и parse
.
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
myObject.regex = undefined;
myObject = JSON.parse(JSON.stringify(myObject));
console.log(myObject);
JSON.parse(JSON.stringify({ ...myObject, regex: undefined }))
Если вы хотите удалить свойство, глубоко вложенное в объект, вы можете использовать следующую рекурсивную функцию с указанием пути к свойству в качестве второго аргумента:
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: {}}}
Использование ES6:
(Оператор Destructuring + Spread)
const myObject = {
regex: "^http://.*",
b: 2,
c: 3
};
const { regex, ...noRegex } = myObject;
console.log(noRegex); // => { b: 2, c: 3 }
Вы можете просто удалить любое свойство объекта, используя ключевое слово delete
.
Например:
var obj = {key1:"val1",key2:"val2",key3:"val3"}
Чтобы удалить любое свойство, например key1
, используйте ключевое слово delete
следующим образом:
delete obj.key1
Или вы также можете использовать массивную нотацию:
delete obj[key1]
Ссылка: MDN.
Рассмотрите возможность создания нового объекта без свойства "regex"
, поскольку исходный объект всегда может ссылаться на другие части вашей программы. Таким образом, вам следует избегать манипулирования им.
const myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
const { regex, ...newMyObject } = myObject;
console.log(newMyObject);
SyntaxError: Unexpected token '...'. Expected a property name.
?
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"];
}
}
);
Утверждение Дэна о том, что "удаление" происходит очень медленно, и поставленный в нем тест был усомнился. Поэтому я сам проверил тест в 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
Обратите внимание, что я специально выполнял несколько операций "удалить" в одном цикле цикла, чтобы минимизировать эффект, вызванный другими операциями.
const myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
const { regex, ...other } = myObject;
console.log(myObject)
console.log(regex)
console.log(other)
Здравствуйте, Вы можете попробовать этот простой вид
var obj = [];
obj.key1 = {name: "John", room: 1234};
obj.key2 = {name: "Jim", room: 1234};
delete(obj.key1);
Попробуйте это
delete myObject['key'];
На этой странице представлено множество различных вариантов, а не потому, что большинство вариантов неверны, или потому, что ответы являются дубликатами, а потому, что соответствующий метод зависит от ситуации, в которой вы находитесь, и целей задач, которые вы и/или вы команда пытается выполнить. Чтобы ответить на ваш вопрос однозначно, нужно знать:
После ответа на эти четыре вопроса в 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
& array в дополнение к строкам и работает в каждой версии JavaScript, за исключением самой первой версии. Однако это мутация, которая нарушает некоторые принципы программирования и имеет последствия для производительности. Это также может привести к неперехваченным исключениям при использовании в неконфигурируемых свойствах в строгом режиме.
Эта категория предназначена для работы с экземплярами простого объекта или массива в новых вариантах ECMAScript, когда требуется не-мутирующий подход, и вам не нужно учитывать ключи Symbol:
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 :(
Эта категория предназначена для работы с объектными литералами или экземплярами объектов, когда вы хотите сохранить/продолжать использовать исходную ссылку, защищая от исключений, возникающих при неконфигурируемых свойствах:
'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 doesn't have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from 'foo' because 'isCool' doesn't 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"
Использование lodash
import omit from 'lodash/omit';
const prevObject = {test: false, test2: true};
// Removes test2 key from previous object
const nextObject = omit(prevObject, 'test2');
Использование Ramda
R.omit(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, c: 3}
@johnstock, мы также можем использовать концепцию прототипирования JavaScript, чтобы добавить метод к объектам для удаления любого переданного ключа, доступного в вызывающем объекте.
Выше ответы приветствуются.
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
// 1st and direct way
delete myObject.regex; // delete myObject["regex"]
console.log(myObject); // { ircEvent: 'PRIVMSG', method: 'newURI' }
// 2 way - by using the concept of JavaScript prototyping concept
Object.prototype.removeFromObjectByKey = function(key) {
// If key exists, remove it and return true
if(this[key] !== undefined) {
delete this[key]
return true;
}
// Else return false
return false;
}
var isRemoved = myObject.removeFromObjectByKey('method')
console.log(myObject) // { ircEvent: 'PRIVMSG' }
// More examples
var obj = { a: 45, b: 56, c: 67}
console.log(obj) // { a: 45, b: 56, c: 67 }
// Remove key 'a' from obj
isRemoved = obj.removeFromObjectByKey('a')
console.log(isRemoved); //true
console.log(obj); // { b: 56, c: 67 }
// Remove key 'd' from obj which doesn't exist
var isRemoved = obj.removeFromObjectByKey('d')
console.log(isRemoved); // false
console.log(obj); // { b: 56, c: 67 }
Очень просто:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
delete myObject.regex;
function removeProperty(obj, prop) {
if(prop in obj){
Reflect.deleteProperty(obj, prop);
return true;
} else {
return false;
}
}
Для
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
delete myObject ["regex"]; Также вы знаете индекс ключа, например. Вам нужно удалить второй ключ (regex), затем
var key = Object.keys(myObject)[2]
delete myObject[key];
Много времени мы требуем удаления основанного на индексах в объекте. Клавиши "Запомните" в объекте могут быть в положении "вверх-вниз", поэтому, пожалуйста, будьте осторожны при использовании
вы можете использовать оператор delete
, как показано ниже.
var multiverse = {
earth1: "Silver Age",
earth2: "Golden Age"
};
delete multiverse.earth2;//will return true if it finds
// Outputs: { earth1: "Silver Age" }
console.log(multiverse);
Оператор delete также имеет return value.
Если ему удастся удалить свойство, оно вернет true. Если ему не удастся удалить свойство, потому что свойство невосстанавливаемо, оно будет return false
, или если в строгом режиме оно выдает ошибку.
Я использовал lodash "unset" , чтобы это произошло и для вложенного объекта.. только для этого нужно написать небольшую логику, чтобы получить путь ключа свойства, который ожидается методом omit.
var a = {"bool":{"must":[{"range":{"price_index.final_price":{"gt":"450","lt":"500"}}},{"bool":{"should":[{"term":{"color_value.keyword":"Black"}}]}}]}};
function getPathOfKey(object,key,currentPath, t){
var currentPath = currentPath || [];
for(var i in object){
if(i == key){
t = currentPath;
}
else if(typeof object[i] == "object"){
currentPath.push(i)
return getPathOfKey(object[i], key,currentPath)
}
}
t.push(key);
return t;
}
document.getElementById("output").innerHTML =JSON.stringify(getPathOfKey(a,"price_index.final_price"))
<div id="output">
</div>
var unset = require('lodash.unset');
unset(a,getPathOfKey(a,"price_index.final_price"));
function removeElement(elementId) {
// Removes an element from the document
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
function addElement(parentId, elementTag, elementId, html) {
// Adds an element to the document
var p = document.getElementById(parentId);
var newElement = document.createElement(elementTag);
newElement.setAttribute('id', elementId);
newElement.innerHTML = html;
p.appendChild(newElement);
}
delete someObject["keyName"];
someObject["keyName"] // undefined