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


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

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

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

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

4807


источник


Ответы:


Как это:

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

демонстрация

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

console.log(myObject);

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


6695



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

Посмотрите на эталонный тест ,

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

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

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

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

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

Это удаляет ключ из хэш-карты ,

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

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

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

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

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

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

object.field === undefined

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

тесты

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

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

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

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

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

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

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

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

Остерегайтесь утечек памяти!

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

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

В приведенном выше коде просто nodeRecords[i][lastTime] = undefined;приведет к массивной утечке памяти из-за каждого кадра анимации. Каждый кадр, все элементы 65536 DOM будут занимать еще 65536 отдельных слотов, но предыдущие слоты 65536 будут установлены только на неопределенные, что оставляет их висящими в памяти. Продолжайте, попробуйте запустить вышеуказанный код в консоли и убедитесь сами. После принудительной ошибки из-за памяти попытайтесь запустить ее заново, за исключением следующей версии кода, который использует deleteоператора.

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

Как видно из приведенного выше фрагмента кода, существуют некоторые редкие подходящие варианты использования для deleteоператор. Однако не беспокойтесь об этой проблеме слишком много. Это станет проблемой только с объектами продолжительной жизни, которые постоянно добавляют к ним новые ключи. В любом другом случае (это почти каждый случай в реальном программировании), наиболее целесообразно использовать obj[prop] = undefined, Основная цель этого раздела - просто обратить ваше внимание на то, чтобы в редких случаях это стало проблемой в вашем коде, тогда вы можете более легко понять проблему и, следовательно, не тратить время на анализ своего кода, чтобы найти и понять эту проблему.

Не всегда установите для undefined

Одним из аспектов Javascript, который важно рассмотреть, является полиморфизм. Полиморфизм - это присвоение одинаковых переменных / слотов в объектах разных типов, как показано ниже.

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

Тем не менее, существуют две основные проблемы, которые невозможно устранить при использовании полиморфных массивов:

  1. Они медленны и неэффективны. При доступе к определенному индексу вместо того, чтобы просто получать глобальный тип для массива, браузер вместо этого должен получать тип на основе индекса, в котором каждый индекс хранит дополнительные метаданные его типа.
  2. После полиморфного, всегда полиморфного. Когда массив сделан полиморфным, полиморфизм не может быть отменен в браузерах Webkit. Таким образом, даже если вы восстановите полиморфный массив как неполиморфный, он все равно будет храниться браузером в виде полиморфного массива.

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

Но, как аналогия с наркотиками связана с deleteоперация? Ответ содержит последнюю строку кода в приведенном выше фрагменте. Таким образом, пусть это будет пересмотрено, на этот раз с завихрением.

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

Обратите внимание. bar[1] = ""не принуждает полиморфизм, тогда как bar[1] = undefinedделает. Поэтому всегда следует, когда это возможно, использовать соответствующий тип для своих объектов, чтобы случайно не вызвать полиморфизм. Один из таких лиц может использовать следующий список в качестве общей ссылки, чтобы получить их. Однако, пожалуйста, не используйте явно указанные ниже идеи. Вместо этого используйте все, что хорошо работает для вашего кода.

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

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


672



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

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

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


188



As others have said, you can use delete. But JavaScript is an OOP Language, so everything is an object. Thus, I feel it necessary to point out a particular caveat.

In arrays, unlike plain old objects, using delete leaves behind garbage in the form of null, creating a "hole" in the array.

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

As you can see, delete doesn't always work as one might expect. The value is overwritten, but the memory is not reallocated.

Ignoring the dangers and problems inherent in null, and the space wasted, this can be problematic if the array needs to be precise.

For example, say you are creating a webapp that uses JSON-serialization to store an array used for 'tabs' in a string (in this case, localStorage). Let's also say that the code uses the numerical indices of the array's members to "title" them when drawing to the screen. Why are you doing this rather than just storing the "title" as well? Because... reasons.

Okay, let's just say that you're trying to save memory at the request of this one user who runs a PDP-11 minicomputer from the 1960's running UNIX, and wrote his own Elinks-based, JavaScript-compliant, line-printer-friendly browser because X11 is out of the question.

Increasingly stupid edge-case scenario aside, using delete on said array will result in null polluting the array, and probably causing bugs in the app later on. And if you check for null, it would straight up skip the numbers resulting in the tabs being rendered like [1] [2] [4] [5] ....

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

Yeah, that's definitely not what you wanted.

Now, you could keep a second iterator, like j, to increment only when valid values are read from the array. But that wouldn't exactly solve the null issue, and you still have to please that troll PDP-11 user. Alas, his computer just doesn't have enough memory to hold that last integer (don't ask how he manages to handle a variable-width array...).

So, he sends you an email in anger:

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

About now, you're at your wit's end. This guy has been complaining non-stop about your app, and you want to tell him to shut up and go get a better computer.

Luckily, arrays do have a specialized method for deleting indices and reallocating memory: Array.prototype.splice(). You could write something like this:

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

And just like that, you've pleased Mr. PDP-11. Hooray! (I'd still tell him off, though...)


126



Old question, modern answer. Using object destructuring, an ECMAScript 6 feature, it's as simple as:

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

Or with the questions sample:

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

You can see it in action in the Babel try-out editor.


Edit:

To reassign to the same variable, use a let:

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

84



Another alternative is to use the Underscore.js library.

Note that _.pick() and _.omit() both return a copy of the object and don't directly modify the original object. Assigning the result to the original object should do the trick (not shown).

Reference: link _.pick(object, *keys)

Return a copy of the object, filtered to only have values for the whitelisted keys (or array of valid keys).

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

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

Reference: link _.omit(object, *keys)

Return a copy of the object, filtered to omit the blacklisted keys (or array of keys).

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

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

For arrays, _.filter() and _.reject() can be used in a similar manner.


62



The term you have used in your question title Remove a property from a JavaScript object, can be interpreted in some different ways. The one is to remove it for whole the memory and the list of object keys or the other is just to remove it from your object. As it has been mentioned in some other answers, the delete keyword is the main part. Let's say you have your object like:

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

If you do:

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

the result would be:

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

You can delete that specific key from your object keys like:

delete myJSONObject["regex"];

Then your objects key using Object.keys(myJSONObject) would be:

["ircEvent", "method"]

But the point is if you care about memory and you want to whole the object gets removed from the memory, it is recommended to set it to null before you delete the key:

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

The other important point here is to be careful about your other references to the same object. For instance, if you create a variable like:

var regex = myJSONObject["regex"];

Or add it as a new pointer to another object like:

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

Then even if you remove it from your object myJSONObject, that specific object won't get deleted from the memory, since the regex variable and myOtherObject["regex"] still have their values. Then how could we remove the object from the memory for sure?

The answer would be to delete all the references you have in your code, pointed to that very object and also not use var statements to create new references to that object. This last point regarding var statements, is one of the most crucial issues that we are usually faced with, because using var statements would prevent the created object from getting removed.

Which means in this case you won't be able to remove that object because you have created the regex variable via a var statement, and if you do:

delete regex; //False

The result would be false, which means that your delete statement haven't been executed as you expected. But if you had not created that variable before, and you only had myOtherObject["regex"] as your last existing reference, you could have done this just by removing it like:

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

In other words, a JavaScript object gets killed as soon as there is no reference left in your code pointed to that object.


Update: Thanks to @AgentME:

Setting a property to null before deleting it doesn't accomplish anything (unless the object has been sealed by Object.seal and the delete fails. That's not usually the case unless you specifically try).

To get more info on Object.seal: Object.seal()


30



ECMAScript 2015 (or ES6) came with built-in Reflect object. It is possible to delete object property by calling Reflect.deleteProperty() function with target object and property key as parameters:

Reflect.deleteProperty(myJSONObject, 'regex');

which is equivalent to:

delete myJSONObject['regex'];

But if the property of the object is not configurable it cannot be deleted neither with deleteProperty function nor delete operator:

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

Object.freeze() makes all properties of object not configurable (besides other things). deleteProperty function (as well as delete operator) returns false when tries to delete any of it's properties. If property is configurable it returns true, even if property does not exist.

The difference between delete and deleteProperty is when using strict mode:

"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

26



Suppose you have an object that looks like this:

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

Deleting an object property

If you want to use the entire staff array, the proper way to do this, would be to do this:

delete Hogwarts.staff;

Alternatively, you could also do this:

delete Hogwarts['staff'];

Similarly, removing the entire students array would be done by calling delete Hogwarts.students; or delete Hogwarts['students'];.

Deleting an array index

Now, if you want to remove a single staff member or student, the procedure is a bit different, because both properties are arrays themselves.

If you know the index of your staff member, you could simply do this:

Hogwarts.staff.splice(3, 1);

If you do not know the index, you'll also have to do an index search:

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

Note

While you technically can use delete for an array, using it would result in getting incorrect results when calling for example Hogwarts.staff.length later on. In other words, delete would remove the element, but it wouldn't update the value of length property. Using delete would also mess up your indexing.

So, when deleting values from an object, always first consider whether you're dealing with object properties or whether you're dealing with array values, and choose the appropriate strategy based on that.

If you want to experiment with this, you can use this Fiddle as a starting point.


26



The delete operator is the best way to do so.

A live example to show:

var foo = {bar: 'bar'};
delete foo.bar;
console.log('bar' in foo); // Logs false, because bar was deleted from foo.

20