如何从javascript关联数组中删除对象?


618

假设我有以下代码:

var myArray = new Object();
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;

现在,如果我想删除“姓氏”?
myArray["lastname"].remove()

(我需要删除元素,因为元素的数量很重要,并且我想保持干净。)


27
提示:不要混淆数组和映射。某些语言(例如php)对于这两种语言都有一个单一的对象。尽管您在此处使用了正确的类型(new Object()),但将其命名为myArray,但这只是语言标准的问题。
Juan Mendes

不要忘记JavaScript是无类型的,所有东西都是对象。请参阅下面的扫罗答案。
2012年

4
@StephanKristyn-确切地说,JS具有类型,但是具有动态弱化的方式。例如,尽管其变量确实是无类型的,但其值不是。这是动态的部分。表示没有严格定义不同值类型之间的运算,而是依赖于幕后转换;例如"Test" + {};,一个完全有效的JS语句。
Saul

Answers:


1134

JavaScript中的对象可以看作是关联数组,将键(属性)映射到值。

要从JavaScript中的对象中删除属性,请使用delete运算符:

const o = { lastName: 'foo' }
o.hasOwnProperty('lastName') // true
delete o['lastName']
o.hasOwnProperty('lastName') // false

请注意,delete将应用于的index属性时Array,您将创建一个稀疏填充的数组(即缺少索引的数组)。

当使用的实例时Array,如果您不想创建一个人口稀少的数组(通常不这样做),则应该使用Array#spliceArray#pop

请注意,deleteJavaScript中的运算符不会直接释放内存。其目的是从对象中删除属性。当然,如果要删除的属性仅保留对object的剩余引用o,则o随后将以常规方式进行垃圾回收。

使用delete运算符可能会影响JavaScript引擎优化 代码的能力。


18
如果将其用于Array对象实例上以删除现有元素(例如),则会导致问题delete myArray[0]。请参阅stackoverflow.com/a/9973592/426379删除数组元素
2012年

4
会引起什么问题?
Gottox 2012年

26
@Gottox- length数组对象的属性保持不变。
Saul 2012年

12
@Saul:如果真的用作数组出现问题myArray-但这不是(myArray是不幸的名字),它是一个对象。因此在这种情况下delete可以。请注意,即使将其创建new Array()为关联数组并用作关联数组,也仍然可以。如果您正在使用实数数组,您的警告仍然需要注意。
johndodo

2
@johndodo-是的。这就是为什么我从对此发表最初评论的原因,如果将其用于Array对象实例,则会引起问题。不过,我更喜欢在所有情况下都能正常执行的方法,请参阅下面的答案。
Saul

79

JavaScript中的所有对象都实现为哈希表/关联数组。因此,以下内容是等效的:

alert(myObj["SomeProperty"]);
alert(myObj.SomeProperty);

并且,delete如前所述,您可以通过关键字从对象中“删除”属性,可以通过两种方式使用它:

delete myObj["SomeProperty"];
delete myObj.SomeProperty;

希望额外的信息有所帮助...


10
应该注意的是,如果该属性不是一个简单的术语,则点符号将不起作用。即myObj['some;property']工作,但myObj.some;property不会(出于明显的原因)。同样,在括号表示法中使用变量也可能并不明显,例如var x = 'SomeProperty'; alert(myObj[x])
Kip

2
“ JavaScript中的所有对象都实现为哈希表/关联数组。”-否。V8倾向于将对象存储为隐藏类+密集字段。只有对它们做一些奇怪的事情(例如删除字段),它才会放弃并在后台使用哈希映射。
约翰·德沃夏克

4
@JanDvorak-嘿,您知道这个答案最初是何时写的,是吗?该描述对于大多数目的过去是并且仍然足够。就是说,我知道自己是乏味的书呆子。:)
Jason Bunting 2015年

41

先前的答案都没有解决Javascript没有关联数组开头的事实-没有这样的array类型,请参见typeof

Javascript具有的是具有动态属性的对象实例。当属性与Array对象实例的元素混淆时,那么Bad Things™必然会发生:

问题

var elements = new Array()

elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]

console.log("number of elements: ", elements.length)   // returns 2
delete elements[1]
console.log("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.log("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.log(elements.length)                        // returns 2
elements.removeItem("prop")
elements.removeItem(0)
console.log(elements.hasOwnProperty("prop"))        // returns false as it should
console.log(elements.length)                        // returns 1 as it should

8
这个解决方案有两个问题:它掩盖了一个事实,即数组和对象在JS中是完全不同的野兽(您知道它,但显然OP却不是),并且它使用了原型。如果OP了解了数组和对象(并且会相应地为变量命名),OP就会更好-试图隐藏两者之间的差异只会给他带来更多麻烦。恕我直言,当然。
johndodo 2012年

1
@johndodo- ArrayJS中的所有都是对象,请尝试typeof new Array();typeof []进行验证。Array只是某种物体,而根本不是“异兽”。在JS中,对象通过其构造函数名称和原型链进行区分,请参见基于原型的编程
Saul

9
您错过了重点。我知道数组也是对象,但这并不意味着明智地使用它们。程序员应该决定是否要使用某些东西作为数组(带有push,pop,[],...)或用作对象/“关联数组”。混搭并不是一个好主意,正是因为您的解决方案试图隐藏问题。如果您事先决定要使用哪种设计模式(数组或对象),就不会有此类问题。
约翰多多

7
@johndodo-您到底在谈论什么问题?以上代码的目的是通过提供简单的多态函数来解决缺陷delete运算符所具有的问题Array
扫罗

1
delete没有缺陷。delete用于删除属性。而已。将delete操作符应用于数组的索引会删除该索引。还需要做什么?剩下的是稀疏数组,这是该语言的功能。如果您不希望使用稀疏数组,请不要删除索引:use splicepop
Ben Aston

35

那只是删除删除对象,但仍保持数组长度不变。

要删除,您需要执行以下操作:

array.splice(index, 1);

11
确实,但是在这种情况下,没有使用数组,只是一个普通的旧对象,因此它没有长度或拼接方法。
MooGoo 2010年

2
@Andreaa Panagiotidis除非我们不谈论数组,否则在100%的情况下都是错误的🙂–
Drenai

17

虽然接受的答案是正确的,但缺少解释其工作原理的解释。

首先,您的代码应反映出这不是数组的事实:

var myObject = new Object();
myObject["firstname"] = "Bob";
myObject["lastname"] = "Smith";
myObject["age"] = 25;

请注意,所有对象(包括 Array)都可以这种方式使用。但是,不要期望标准的JS数组函数(pop,push等)可以在对象上工作!

如接受答案中所述,您可以使用delete来从对象中删除条目:

delete myObject["lastname"]

您应该确定要采取的路线-使用对象(关联数组/字典)还是使用数组(地图)。切勿将两者混在一起。


6
很好的答案。我只建议阅读此书的任何人都不应将javascript中的数组抽象为“列表”,而应抽象为“列表”。这是因为使用数组时,您不应该尝试控制元素的索引。如果您尝试......,
那就

6

使用方法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");

1
这是一种更为通用的解决方案,可以添加到您的js文件中,并且该方法将对所有数组可用,而不仅仅是一个数组。
侯赛因

6

正如其他答案所指出的那样,您使用的不是Javascript数组,而是Javascript对象,该对象几乎与其他语言中的关联数组一样工作,只是所有键都转换为字符串。新的Map将键存储为其原始类型。

如果您有一个数组而不是一个对象,则可以使用该数组的.filter函数来返回一个新的数组,而不删除要删除的项目:

var myArray = ['Bob', 'Smith', 25];
myArray = myArray.filter(function(item) {
    return item !== 'Smith';
});

如果你有一个旧的浏览器和jQuery,jQuery有一个$.grep方法是工作方式类似:

myArray = $.grep(myArray, function(item) {
    return item !== 'Smith';
});

完美的解释。我使用过滤器来达到预期的效果。您能否解释一下返回项如何从数组中删除对象。我假设它返回数组,只要它不包含您包含的字符串即可。
爱德华


5

您正在使用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
    }

4

您可以通过将其明确分配给“未定义”来从地图中删除该条目。如您的情况:

myArray [“ lastname”] =未定义;


如果不确定该字典中是否存在该密钥,但想对其进行清理,则这可能很有用。如果我错了Amytis,请纠正我。
哈桑·拜格,2018年

3

如果出于某种原因删除键不起作用(例如它对我不起作用)

您可以将其拼接起来,然后过滤未定义的值

// to cut out one element via arr.splice(indexToRemove, numberToRemove);
array.splice(key, 1)
array.filter(function(n){return n});

不要尝试将它们链接起来,因为拼接会返回已删除的元素;


3

我们也可以将其用作功能。如果用作原型,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");


1

通过使用"delete"关键字,它将从javascript中的array中删除array元素。

例如,

考虑以下陈述。

var arrayElementToDelete = new Object();

arrayElementToDelete["id"]           = "XERTYB00G1"; 
arrayElementToDelete["first_name"]   = "Employee_one";
arrayElementToDelete["status"]       = "Active"; 

delete arrayElementToDelete["status"];

代码的最后一行将从数组中删除键为“状态”的数组元素。


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

没有循环/迭代,我们得到相同的结果


0

对于“数组”:

如果您知道索引:

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和数组的长度不变。在某些情况下,这可能是个问题。

例如,如果我通过delete它删除myArray之后在myArray.toString()上创建了空条目,即,


0

对我来说唯一的工作方法是:

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"]

为什么不使用过滤器呢?这是过滤器的理想用例
Code Maniac
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.