如何通过值删除JavaScript对象中的某一项?

7
例如,考虑以下对象:

举个例子:

var fruits = {
    "red" : "apple",
    "blue" : "blueberry",
    "yellow" : "banana"
}

我知道可以使用delete fruits["red"]根据键名删除,但是如何通过水果名称删除对象项呢?


https://dev59.com/kmkw5IYBdhLWcg3waZ74#9907509 - jAndy
我相信MDM的解决方案是实现这个功能的唯一途径,我很好奇是否有人有更聪明的方法... - jbabey
9个回答

10

你尝试过像这样的方法吗?

function deleteByValue(val) {
    for(var f in fruits) {
        if(fruits[f] == val) {
            delete fruits[f];
        }
    }
}

根据 Rocket 的评论,你可能需要检查 hasOwnProperty 来确保你不会删除对象原型中的成员:

function deleteByValue(val) {
    for(var f in fruits) {
        if(fruits.hasOwnProperty(f) && fruits[f] == val) {
            delete fruits[f];
        }
    }
}

JS在迭代器中删除一个项目时不是那么挑剔吗?(我可能只是在额外保险,但不知道你是否有绝对的答案)。 - Brad Christie
2
你不应该在 for...in 循环内部检查 hasOwnProperty 吗? - gen_Eric
@BradChristie 对我来说它从来没有挑剔过,在Chrome的控制台中进行了快速测试,确认它足够愉快地执行此操作,尽管在不同的浏览器中可能会有所不同。 - mdm
1
如果你找到了一个键,你应该跳过循环的剩余部分,因为它不会再次出现。 - YMMD
2
您正在按值而非键进行删除操作,而某个值可能会出现两次。键保证只会出现一次。 - Jarrett Meyer
1
哦,没错。我的错。对不起! - YMMD

1
var key = null;
for (var k in fruits){
  if (fruits[k] === 'apple'){
    key = k;
    break;
  }
}
if (key != null)
  delete fruits[key];

遍历对象,找到相应的键,然后删除它(如果找到)。


1
你不应该在 for...in 循环内部检查 hasOwnProperty 吗? - gen_Eric

1

不知道这种处理方式是否高效,但使用filter函数可以用三行代码完成:

var fruits = {
    "red" : "apple",
    "blue" : "blueberry",
    "yellow" : "banana"
}

var appleless_keys = Object.keys(fruits).filter(this_fruit => fruits[this_fruit] !== "apple");
appleless_obj = {};
appleless_keys.forEach(key => appleless_obj[key] = fruits[key]);
console.dir(appleless_obj);

或者作为一个函数:

var fruits = {
    "red" : "apple",
    "blue" : "blueberry",
    "yellow" : "banana"
}

function remove_fruit(fruit_to_remove,fruits){
  var new_keys = Object.keys(fruits).filter(this_fruit => fruits[this_fruit] !== fruit_to_remove);
  new_obj = {};
  new_keys.forEach(key => new_obj[key] = fruits[key]);  
  return new_obj;
}

console.dir(remove_fruit("apple",fruits));


1

使用关键词删除进行简化,

function stripProperty(o, v) {
    return  (delete o[Object.keys(o).splice(Object.values(o).indexOf(v), 1)])?o:0;
}   

    var fruits = {
        "red" : "apple",
        "blue" : "blueberry",
        "yellow" : "banana"
    }

    function stripProperty(o, v) {
        return  (delete o[Object.keys(o).splice(Object.values(o).indexOf(v), 1)])?o:0;
    }   


    console.log(stripProperty(fruits, 'banana'));

使用方法,

var fruits = {
    "red" : "apple",
    "blue" : "blueberry",
    "yellow" : "banana"
}

console.log(stripProperty(fruits, 'apple'))

0

这个怎么样?

function delteByValue(a){
  fruits.foreach( function( k, v ) {
    if (fruits[v] == a){
      delete fruits[k];
    }
  });
}

0
我认为创建一个函数并覆盖Object.prototype是个好主意。
/**
 *  @autor Javier Cobos
 *  @param value The value to look for
 *  @return true if founded deleted, false if not
 */        
Object.prototype.removeByValue = function(value){
         var i;
         for(i in this){
            if(this.hasOwnProperty(i))
                if(value === this[i]){
                   delete(this[i]);
                   return true;
                }
         }   
         return false;
        }

// Example
     var fruits = {
        "red" : "apple",
        "blue" : "blueberry",
        "yellow" : "banana"
    }

        fruits .removeByValue("apple");

这样我们在脚本中的每个对象都有了一个新的方法 :)


在IE<=8中,扩展Object.prototype和Array.prototype会创建许多表面问题...最好将这样的方法添加到实用程序(如Underscore或jQuery)中。$.removeByValue = function(object, value) { ... }(注意:这些问题往往出现在处理第三方脚本(如Google Analytics或广告)时) - Tracker1
也许你可以将这个功能封装到你正在使用的函数中,以避免冲突。 - Javier Cobos

0

我知道你现在有几个可接受的答案... 我将包含一个通用函数来解决这个问题...

// NOTE, replace "Object.removePropertyByValue" 
// with say "jQuery.removePropertyByValue" or "_.removePropertyByValue"
// to create a jQuery or Underscore extension.
Object.removePropertyByValue = function(obj, val) {
  //store list of properties to remove
  var propsToRemove = [];

  for (var prop in obj) {
    if (obj.hasOwnProperty(prop) && obj[prop] === val) {
      //save the property name here, deleting while enumerating is a bad idea.
      propsToRemove.push(prop);
    }
  }

  //remove all the items stored.
  while (propsToRemove.length) delete obj[propsToRemove.pop()];
}

从这里,你应该能够调用:Object.removePropertyByValue(fruits, "red");

将方法绑定到Object构造函数是安全的,但扩展Object.prototype(或Array.prototype)是不安全的,因为第三方脚本中存在许多意想不到的后果。(看着你,Google) - Tracker1

0

使用这个函数

function delobj(obj,val){
    for (x in obj) {
        if(obj[x] == val)
        delete obj[x]
    }
    return obj;
}

使用方法如下

delobj(object "object name",string "value of element")

未捕获的 TypeError:x.filter 不是一个函数? - Aamir

-1
你可以使用splice方法。
fruits.splice($.inArray("red", fruits), 1);

但这当然使用了jQuery。

您还可以使用此扩展:

Array.prototype.remove = function () {
    var what, a = arguments, L = a.length, ax;
    while (L && this.length) {
        what = a[--L];
        while ((ax = this.indexOf(what)) != -1) {
            this.splice(ax, 1);
        }
    }
    return this;
}

1
这是一个对象,不是一个数组。 - Tracker1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接