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

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

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

let myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI"
};
6882
johnstok 16 Окт 2008 в 14:57

29 ответов

Лучший ответ

Нравится:

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

Для тех, кто хочет больше узнать об этом, пользователь Staa Overflow kangax написал невероятно подробное сообщение в блоге о {{ X0}} в своем блоге, Общие сведения об удалении . Настоятельно рекомендуется.

8150
Jonathan 9 Окт 2017 в 16:55

Вы можете использовать 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://.*" }
6
Bhargav Patel 10 Апр 2019 в 20:40

Попробуйте следующий метод. Назначьте значение свойства 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
Peter Mortensen 22 Ноя 2016 в 22:12

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

94
Thaddeus Albers 3 Фев 2018 в 19:51

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

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

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

console.log(newMyObject);
6
ideaboxer 23 Окт 2017 в 10:06

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

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

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

14
Amio.io 28 Ноя 2016 в 15:14

Этот пост очень старый, и я нахожу его очень полезным, поэтому я решил поделиться функцией unset, которую я написал, на тот случай, если кто-то еще увидит этот пост и подумает, почему это не так просто, как в функции 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
Peter Mortensen 22 Ноя 2016 в 21:35

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

myObject = _.omit(myObject, 'regex');
29
emil 21 Янв 2019 в 11:24

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

Живой пример, чтобы показать:

var foo = {bar: 'bar'};
delete foo.bar;
console.log('bar' in foo); // Logs false, because bar was deleted from foo.
29
Peter Mortensen 11 Фев 2016 в 20:30

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

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

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

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

console.log(foo);  // 1
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;
93
Lior Elrom 18 Дек 2019 в 15:36

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

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

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

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

39
John Slegers 23 Ноя 2016 в 09:17
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
    
delete myObject.regex;

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

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

244
str 1 Июн 2018 в 16:29

Используя ES6:

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

const myObject = {
    regex: "^http://.*",
    b: 2,
    c: 3
};
const { regex, ...noRegex } = myObject;
console.log(noRegex); // => { b: 2, c: 3 }
36
kalehmann 6 Июн 2019 в 13:25

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

Например

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

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

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

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

18
Willem 15 Сен 2014 в 00:48

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

Например:

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

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

delete obj.key1

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

delete obj[key1]

Ссылка: MDN.

7
Peter Mortensen 22 Ноя 2016 в 22:11

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

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

25
Alireza 16 Апр 2019 в 23:22

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"];
        }
    }
);
7
xgqfrms-gildata 10 Ноя 2017 в 06:36

Другое решение, использующее {{X0} } .

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

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

( 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
kind user 24 Окт 2017 в 09:58

Попробуй это

delete myObject['key'];
5
codemirror 26 Май 2017 в 06:58

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

var obj = [];

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

delete(obj.key1);
5
Gohel Dhaval 26 Май 2017 в 09:28

Утверждение Дэна о том, что «удаление» очень медленное, и опубликованный им тест были поставлены под сомнение. Итак, я провел тест самостоятельно в 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
Chong Lip Phang 26 Июл 2017 в 07:19

Оператор 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, что оставляет {{X9} } еще в памяти. Следовательно, в ситуациях, когда создается и удаляется много ключей, использование 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 слотов будет установлено только значение undefined, что приведет к их зависанию в памяти. Продолжайте, попробуйте запустить приведенный выше код в консоли и убедитесь сами. После возникновения ошибки нехватки памяти попробуйте запустить ее снова, за исключением следующей версии кода, в которой вместо этого используется оператор 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. Таким образом, даже если вы вернете полиморфный массив в неполиморфный, он все равно будет сохранен браузером как полиморфный массив.

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

Но как аналогия поездки с наркотиками связана с 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.

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

929
Community 19 Апр 2018 в 10:26

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

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
ayushgp 23 Июн 2016 в 09:38
const myObject = {
        "ircEvent": "PRIVMSG",
        "method": "newURI",
        "regex": "^http://.*"
    };

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

console.log(myObject)
console.log(regex)
console.log(other)
6
xiang 6 Фев 2018 в 04:28

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


< Сильный > Edit:

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

let myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
({ regex, ...myObject } = myObject);
console.log(myObject);
182
Koen. 1 Дек 2016 в 20:51

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

Например:

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 }) }), {})

< Сильный > < EM> Использование

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

< Сильный > < EM> Или

    const propsToRemove = ['a', 'b']
    object = removeProperties(object, ...propsToRemove) // result => { c: 3 }
27
YairTawil 23 Май 2019 в 09:02

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

Reflect.deleteProperty(myJSONObject, 'regex');

Что эквивалентно:

delete myJSONObject['regex'];

Но если свойство объекта не настраивается, его нельзя удалить ни с помощью функции deleteProperty, ни с помощью оператора delete:

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
40
madox2 25 Янв 2016 в 17:22

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

48
Mehran Hatami 2 Июн 2015 в 22:18

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


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

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

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

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

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

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

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

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

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

В массивах, в отличие от простых старых объектов, использование delete оставляет мусор в виде null, создавая «дыру» в массиве.

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

Как видите, delete не всегда работает так, как можно было ожидать. Значение перезаписывается, но память не перераспределяется. То есть array[4] не перемещен в array[3]. Что в отличие от Array.prototype.unshift, который вставляет элемент в начало массива и сдвигает все вверх (array[0] становится array[1] и т. Д.)

Честно говоря, кроме установки null, а не undefined - что на самом деле странно - такое поведение не должно быть удивительным, поскольку delete является унарным оператор, такой как typeof, который жестко вписан в язык и не должен заботиться о типе объекта, на котором он используется, тогда как Array является подклассом Object с методами , специально разработанными для работы с массивами. Так что delete нет веской причины готовить специальный случай для повторного смещения массива, поскольку это просто замедлит работу с ненужной работой. Оглядываясь назад, мои ожидания были нереальными.

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

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

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

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

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

Придуманный и многословный сценарий PDP-11

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

Хорошо, давайте просто скажем, что вы пытаетесь сэкономить память по запросу этого одного пользователя, который запускает мини-компьютер PDP-11 из UNIX 1960-х годов и написал свой собственный JavaScript-совместимый на основе Elinks браузер, удобный для печати на принтере, потому что 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

К счастью, массивы do имеют специальный метод для удаления индексов и перераспределения памяти: Array.prototype.splice(). Вы могли бы написать что-то вроде этого:

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

И именно так вы порадовали мистера PDP-11. Ура! (я бы все равно отчитал его ...)

Array.prototype.splice vs Array.prototype.slice

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

Array.prototype.splice (начало, n)

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

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

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

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

Array.prototype.slice (начало, конец)

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

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

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

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

На самом деле это не то, что происходит, но так проще думать. Согласно MDN, вот что на самом деле происходит:

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

Индекс, указанный end, просто исключается из среза. Индексы в скобках указывают на то, что вырезано. В любом случае, поведение не является интуитивно понятным, и оно неизбежно вызовет значительную долю ошибок «один на один», поэтому может оказаться полезным создать функцию-обертку, чтобы более точно имитировать поведение .splice():

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

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

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

    return null;
}

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

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

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

Обратите внимание, что функция-обертка разработана очень строго к типам и будет возвращать null, если что-то отключено. Это включает в себя вставку строки вроде "3". Программист должен быть усердным в своих типах. Это должно поощрять хорошую практику программирования.

Обновление относительно is_array()

Это в отношении этого (теперь удаленного) фрагмента:

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

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

209
Braden Best 27 Апр 2019 в 03:47