Предположим, у меня есть такой код:
var myArray = new Object();
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;
Если бы я хотел удалить "фамилию"? .... есть ли какой-нибудь эквивалент
myArray["lastname"].remove()?
(Мне нужно убрать элемент, потому что количество элементов важно, и я хочу, чтобы все было в чистоте.)
Не забывайте, что JavaScript не имеет типов и все является объектом. См. Ответ Саула ниже.
@StephanKristyn - если быть точным, в JS есть типы, но в стиле динамичный и слабый. Например, хотя его переменные действительно не имеют типа, их значения - нет. Это часть динамичный. Слабый означает, что операции между разными типами значений не определены строго и полагаются на скрытые преобразования; например, "Test" + {}; - это совершенно корректный оператор JS.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Объекты в JavaScript можно рассматривать как ассоциативные массивы, отображающие ключи (свойства) в значения.
Чтобы удалить свойство из объекта в JavaScript, вы используете оператор delete:
const o = { lastName: 'foo' }
o.hasOwnProperty('lastName') // true
delete o['lastName']
o.hasOwnProperty('lastName') // false
Обратите внимание, что когда delete применяется к свойству индекса Array, вы создаете малонаселенный массив (т. Е. Массив с отсутствующим индексом).
При работе с экземплярами Array, если вы не хотите создавать редко заполненный массив - а вы обычно этого не делаете - тогда вам следует использовать Array#splice или Array#pop.
Обратите внимание, что оператор delete в JavaScript не освобождает память напрямую. Его цель - удалить свойства с объектов. Конечно, если удаляемое свойство содержит единственную оставшуюся ссылку на объект o, то o впоследствии будет обработан сборщиком мусора обычным способом.
Использование оператора delete может повлиять на способность движков JavaScript к оптимизироватькод.
Это вызовет проблемы при использовании в экземпляре объекта Array для удаления существующего элемента, например. delete myArray[0]. См. stackoverflow.com/a/9973592/426379 и Удаление элементов массива.
Какие проблемы возникнут?
@Gottox - свойство length объекта Array остается неизменным.
@Saul: есть проблемы с бы, если myArray действительно использовался как массив - но это не так (myArray - неудачное имя), это объект. Так что в этом случае delete в порядке. Обратите внимание, что даже если бы он был создан как new Array() и использовался как ассоциативный массив, он все равно был бы в порядке. Ваше предупреждение по-прежнему нужно знать, если вы используете реальные массивы.
@johndodo - Верно. Вот почему я начал свой первоначальный комментарий с Это вызовет проблемы если, используемый в экземпляре объекта Множество. Тем не менее я предпочитаю подход, который работает правильно во всех случаях, см. Мой ответ ниже.
@Saul: см. Мой комментарий под вашим ответом.
@kamal - нет. Что хотите можно найти здесь
Правильно ли его использовать, если элемент не существует в массиве?
Удаляет ли это также объекты, на которые есть ссылки? Что, если myArray ["lastname"] был ссылкой?
@ whiterook6 В Javascript нет ничего "деструктора". Поведение «удаления» простое и просто делает следующую переменную неопределенной.
Работает с объектами. Массивы будут иметь неопределенные значения.
Что происходит, когда вы пытаетесь удалить несуществующий атрибут?
Что, если я хочу удалить «фамилию» из 3D-массива?
В JavaScript нет многомерных массивов. Однако возможны вложенные массивы.
Все объекты в JavaScript реализованы в виде хэш-таблиц / ассоциативных массивов. Итак, следующие эквиваленты:
alert(myObj["SomeProperty"]);
alert(myObj.SomeProperty);
И, как уже указывалось, вы «удаляете» свойство из объекта с помощью ключевого слова delete, которое можно использовать двумя способами:
delete myObj["SomeProperty"];
delete myObj.SomeProperty;
Надеюсь, дополнительная информация поможет ...
Следует отметить, что точечная нотация не работает, если свойство не является простым термином. то есть myObj['some;property'] работает, а myObj.some;property - нет (по понятным причинам). Также может быть неочевидно, что вы можете использовать переменную в обозначении скобок, то есть var x = 'SomeProperty'; alert(myObj[x]).
«Все объекты в JavaScript реализованы в виде хэш-таблиц / ассоциативных массивов.» - false. V8 предпочитает хранить объект как скрытый класс + плотно упакованные поля. Только если вы делаете с ними странные вещи (например, удаляете поля), он сдаётся и использует хэш-карту за кулисами.
@JanDvorak - эй, ты узнал, когда был написан этот ответ, да? Это описание было и остается достаточным для большинства целей. Тем не менее, я понимаю, что это утомительно педантично. :)
При этом удаляется только объект, но длина массива остается неизменной.
Чтобы удалить элемент из массива, вам нужно сделать что-то вроде:
array.splice(index, 1);
В самом деле, но в этом случае массив не используется, просто старый простой объект, поэтому у него нет длины или метода сращивания.
@Andreaa Panagiotidis За исключением случаев, когда мы говорим о массивах, и в этом случае это неверно в 100% случаев ?
Вы используете Object, и у вас нет ассоциативного массива для начала. В ассоциативном массиве добавление и удаление элементов происходит следующим образом:
Array.prototype.contains = function(obj)
{
var i = this.length;
while (i--)
{
if (this[i] === obj)
{
return true;
}
}
return false;
}
Array.prototype.add = function(key, value)
{
if (this.contains(key))
this[key] = value;
else
{
this.push(key);
this[key] = value;
}
}
Array.prototype.remove = function(key)
{
for(var i = 0; i < this.length; ++i)
{
if (this[i] == key)
{
this.splice(i, 1);
return;
}
}
}
// Read a page's GET URL variables and return them as an associative array.
function getUrlVars()
{
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
function ForwardAndHideVariables() {
var dictParameters = getUrlVars();
dictParameters.add("mno", "pqr");
dictParameters.add("mno", "stfu");
dictParameters.remove("mno");
for(var i = 0; i < dictParameters.length; i++)
{
var key = dictParameters[i];
var value = dictParameters[key];
alert(key + " = " + value);
}
// And now forward with HTTP-POST
aa_post_to_url("Default.aspx", dictParameters);
}
function aa_post_to_url(path, params, method) {
method = method || "post";
var form = document.createElement("form");
// Move the submit function to another variable
// so that it doesn't get written over if a parameter name is 'submit'
form._submit_function_ = form.submit;
form.setAttribute("method", method);
form.setAttribute("action", path);
for(var i = 0; i < params.length; i++)
{
var key = params[i];
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
document.body.appendChild(form);
form._submit_function_(); // Call the renamed function
}
Ни один из предыдущих ответов не касается того факта, что JavaScript не имеет ассоциативных массивов для начала - нет типа array как такового, см. typeof.
В JavaScript есть экземпляры объектов с динамическими свойствами. Когда свойства путают с элементами экземпляра объекта Array, неизбежно происходят Плохие Вещи ™:
var elements = new Array()
elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]
console.info("number of elements: ", elements.length) // Returns 2
delete elements[1]
console.info("number of elements: ", elements.length) // Returns 2 (?!)
for (var i = 0; i < elements.length; i++)
{
// Uh-oh... throws a TypeError when i == 1
elements[i].onmouseover = function () { window.alert("Over It.")}
console.info("success at index: ", i)
}
Чтобы иметь универсальную функцию удаления, которая не взорвет вас, используйте:
Object.prototype.removeItem = function (key) {
if (!this.hasOwnProperty(key))
return
if (isNaN(parseInt(key)) || !(this instanceof Array))
delete this[key]
else
this.splice(key, 1)
};
//
// Code sample.
//
var elements = new Array()
elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]
console.info(elements.length) // Returns 2
elements.removeItem("prop")
elements.removeItem(0)
console.info(elements.hasOwnProperty("prop")) // Returns false as it should
console.info(elements.length) // returns 1 as it should
У этого решения есть две проблемы: оно скрывает тот факт, что массивы и объекты - это совершенно разные звери в JS (вы это знаете, но, по-видимому, OP нет), и оно использует прототипы. OP было бы лучше, если бы он узнал о массивах и объектах (и называл бы свои переменные соответственно) - попытка скрыть различия между ними только доставит ему больше проблем. ИМХО конечно.
@johndodo - все Array в JS являются объектами, попробуйте typeof new Array(); или typeof [] для проверки. Array - это просто объект определенного типа, а вовсе не «другой зверь». В JS объекты различаются по имени конструктора и цепочке прототипов, см. Программирование на основе прототипов.
Вы упускаете суть. Я знаю, что массивы тоже являются объектами, но это не значит, что их разумно использовать как таковые. Программист должен решить, хочет ли он использовать что-либо как массив (с push, pop, [], ...) или как объект / «ассоциативный массив». Смешивать и сочетать - не лучший рецепт именно из-за проблем, которые ваше решение пытается скрыть. Если вы заранее решите, какой шаблон проектирования использовать (массив или объект), таких проблем не будет.
@johndodo - О каких конкретно проблемах ты говоришь? Целью приведенного выше кода является устранение недостатка оператора delete в отношении Array путем предоставления простой полиморфной функции.
delete не имеет дефицита. delete предназначен для удаления свойств. Вот и все. Применение оператора удаления к индексу массива удаляет этот индекс. Что еще нужно сделать? У вас остается разреженный массив, что является особенностью языка. Если вам не нужен разреженный массив, не удаляйте индекс: используйте splice или pop.
@BenAston Да, глядя на это сейчас, после стольких лет, я согласен. Разреженные массивы действительно являются особенностью языка, а удаление действительно просто предназначено для удаления свойств. Теперь все, что мне нужно сделать, это выяснить, как найти мотивацию для удаления ответа, который принес мне около 450 очков репутации :-)
@BenAston Да ... или 442 балла, если быть точным. Так что, кто знает, может быть, некоторые из этих голосов были даны не за "обходной путь", а за некоторые полезные идеи в целом :-) В любом случае, спасибо за внимание к дезинформированным частям и разъяснениям!
Хотя принятый ответ правильный, в нем отсутствует объяснение, почему он работает.
Прежде всего, ваш код должен отражать тот факт, что это нет массив:
var myObject = new Object();
myObject["firstname"] = "Bob";
myObject["lastname"] = "Smith";
myObject["age"] = 25;
Обратите внимание, что таким образом можно использовать все объекты (включая Array). Однако не стоит ожидать, что стандартные функции массива JavaScript (pop, push и т. д.) Будут работать с объектами!
Как сказано в принятом ответе, вы можете использовать delete для удаления записей из объектов:
delete myObject["lastname"]
Вы должны решить, какой маршрут вы хотите выбрать - либо использовать объекты (ассоциативные массивы / словари), либо использовать массивы (карты). Никогда не смешивайте их двоих.
Очень хороший ответ. Я бы посоветовал всем, кто читает это, не абстрагировать массивы в javascript как «карты», а скорее как «списки». Это потому, что вы не должны пытаться контролировать индекс элементов при использовании массивов. Если ты попробуешь это ... ну, только не надо: D
Как отмечали другие ответы, вы используете не массив JavaScript, а объект JavaScript, который работает почти как ассоциативный массив на других языках, за исключением того, что все ключи преобразуются в строки. Новый карта хранит ключи как их исходный тип.
Если у вас есть массив, а не объект, вы можете использовать функцию массива .фильтр, чтобы вернуть новый массив без элемента, который вы хотите удалить:
var myArray = ['Bob', 'Smith', 25];
myArray = myArray.filter(function(item) {
return item !== 'Smith';
});
Если у вас более старый браузер и jQuery, в jQuery есть метод $.grep, который работает аналогично:
myArray = $.grep(myArray, function(item) {
return item !== 'Smith';
});
прекрасное объяснение. Я использовал фильтр, чтобы добиться желаемого результата. Не могли бы вы объяснить, как работает возвращаемый элемент для удаления объекта из массива. Я предполагаю, что он возвращает массив, если он не включает строку, которую вы включили.
Если по какой-либо причине клавиша удаления не работает (например, у меня она не работает), вы можете разделить ее, а затем отфильтровать неопределенные значения:
// To cut out one element via arr.splice(indexToRemove, numberToRemove);
array.splice(key, 1)
array.filter(function(n){return n});
Не пытайтесь соединить их в цепочку, так как splice возвращает удаленные элементы;
Это очень просто, если в вашем проекте есть зависимость Underscore.js -
_.omit(myArray, "lastname")
Используя ключевое слово "delete", он удалит элемент массива из массива в JavaScript.
Например,
Рассмотрим следующие утверждения.
var arrayElementToDelete = new Object();
arrayElementToDelete["id"] = "XERTYB00G1";
arrayElementToDelete["first_name"] = "Employee_one";
arrayElementToDelete["status"] = "Active";
delete arrayElementToDelete["status"];
Последняя строка кода удалит из массива элемент, ключ которого имеет значение «status».
Вы можете удалить запись с карты, явно присвоив ей значение undefined. Как и в вашем случае:
myArray["lastname"] = undefined;
Это может быть полезно в тех случаях, когда кто-то не уверен, существует ли ключ в словаре, но хочет очистить его, если он есть. Поправьте меня, если я ошибаюсь, Амитис.
Используйте метод splice, чтобы полностью удалить элемент из массива объектов:
Object.prototype.removeItem = function (key, value) {
if (value == undefined)
return;
for (var i in this) {
if (this[i][key] == value) {
this.splice(i, 1);
}
}
};
var collection = [
{ id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
{ id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
{ id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];
collection.removeItem("id", "87353080-8f49-46b9-9281-162a41ddb8df");
это более общее решение, его можно добавить в ваш файл js, и метод будет доступен для всех массивов, а не только для одного массива.
Мы также можем использовать его как функцию. Angular выдает некоторую ошибку, если используется в качестве прототипа. Спасибо @HarpyWar. Это помогло мне решить проблему.
var removeItem = function (object, key, value) {
if (value == undefined)
return;
for (var i in object) {
if (object[i][key] == value) {
object.splice(i, 1);
}
}
};
var collection = [
{ id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
{ id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
{ id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];
removeItem(collection, "id", "87353080-8f49-46b9-9281-162a41ddb8df");
var myArray = newmyArray = new Object();
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;
var s = JSON.stringify(myArray);
s.replace(/"lastname[^,}]+,/g, '');
newmyArray = JSON.parse(p);
Без цикла / итераций мы получаем тот же результат.
В Руководстве по стилю Airbnb есть элегантный способ сделать это (ECMAScript 7):
const myObject = {
a: 1,
b: 2,
c: 3
};
const { a, ...noA } = myObject;
console.info(noA); // => { b: 2, c: 3 }
Авторское право: https://codeburst.io/use-es2015-object-rest-operator-to-omit-properties-38a3ecffe90
Для «Массивов»:
Если вы знаете индекс:
array.splice(index, 1);
Если вы знаете значение:
function removeItem(array, value) {
var index = array.indexOf(value);
if (index > -1) {
array.splice(index, 1);
}
return array;
}
Самый популярный ответ для delete хорошо работает в случае объектов, но не для реальных массивов. Если я использую delete, он удаляет элементы из циклов, но сохраняет элемент как empty, а длина массива не изменяется. В некоторых случаях это может быть проблемой.
Например, если я выполняю myArray.toString () на myArray после удаления через delete, он создает пустую запись, то есть ,,.
Единственный рабочий метод для меня:
function removeItem (array, value) {
var i = 0;
while (i < array.length) {
if (array[i] === value) {
array.splice(i, 1);
} else {
++i;
}
}
return array;
}
Использование:
var new = removeItem( ["apple","banana", "orange"], "apple");
// ---> ["banana", "orange"]
Почему бы вместо этого не использовать фильтр? это идеальный вариант использования фильтра
Совет: не путайте массивы и карты. Некоторые языки, например php, имеют один объект для обоих. Хотя вы использовали здесь правильный тип (new Object ()), вы назвали его myArray, это просто вопрос стандартов для языка.