【问题标题】:Javascript: remove an object inside another one [duplicate]如何从 JavaScript 对象中删除属性?
【发布时间】:2022-07-06 21:53:03
【问题描述】:

给定一个对象:

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

如何删除属性regex 以得到以下myObject

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

【问题讨论】:

    标签: javascript object oop properties


    【解决方案1】:

    要从对象中删除属性(改变对象),您可以这样做:

    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 在他们的博客 Understanding delete 上写了一篇关于 delete 声明的非常深入的博文。强烈推荐。

    如果您想要一个 new 对象,其中包含除一些之外的所有原始键,您可以使用 destructuring

    演示

    let myObject = {
      "ircEvent": "PRIVMSG",
      "method": "newURI",
      "regex": "^http://.*"
    };
    
    const {regex, ...newObj} = myObject;
    
    console.log(newObj);   // has no 'regex' key
    console.log(myObject); // remains unchanged

    【讨论】:

    • 这是一个不错的方法,但只有当你真的要使用regex时才好,否则eslint会抱怨一个未使用的变量。
    • @Loolooii 您可以重命名解构赋值中的变量以满足no-unused-vars 规则中的argsIgnorePattern。容易解决的问题。
    • 我用这种方法遇到的问题是,如果破坏是在条件内,它会让 ESlint 变得疯狂。
    • 文章消失了——好内容消失了真是太伤心了,很高兴我们有回程机器:web.archive.org/web/20210224201033/http://perfectionkills.com/… :)
    • 了解删除文章:我发现 URL perfectionkills.com/understanding-delete 有效(没有最后一个斜杠)
    【解决方案2】:

    JavaScript 中的对象可以被认为是键和值之间的映射。 delete 运算符用于删除这些键,通常称为对象属性,一次一个。

    var obj = {
      myProperty: 1    
    }
    console.log(obj.hasOwnProperty('myProperty')) // true
    delete obj.myProperty
    console.log(obj.hasOwnProperty('myProperty')) // false

    delete 运算符不直接释放内存,它与简单地将 nullundefined 的值分配给属性不同,因为属性 本身 从目的。请注意,如果已删除属性的 value 是引用类型(对象),并且程序的另一部分仍然持有对该对象的引用,那么该对象当然不会是垃圾直到所有对它的引用都消失为止。

    delete 仅适用于描述符将其标记为可配置的属性。

    【讨论】:

      【解决方案3】:

      老问题,现代答案。使用对象解构,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);
      

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


      编辑:

      要重新分配给同一个变量,请使用let

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

      【讨论】:

      • 如果属性名称不同,我如何解构,即如果我将它放在变量中?
      • 请参阅下面的答案; stackoverflow.com/a/52301527
      • 为什么这比delete()更可取? “现代”并不是真正的原因......
      • 我不是说它是,我是在提供另一种选择。虽然 delete 曾经有一些性能影响,我认为这已经在本页的其他答案中进行了描述。
      • @GreenAsJade 你喜欢这个的一个重要原因是它不会改变原始对象。对于像 React 这样的框架非常重要。我实际上是在寻找一个不会改变原始对象的答案。
      【解决方案4】:

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

      这适用于 Firefox 和 Internet Explorer,我认为它适用于所有其他。

      【讨论】:

        【解决方案5】:

        delete 运算符用于从对象中删除属性。

        const obj = { foo: "bar" };
        
        delete obj.foo;
        obj.hasOwnProperty("foo"); // false
        

        请注意,对于数组,这与删除元素不同。要从数组中删除元素,请使用 Array#spliceArray#pop。例如:

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

        详情

        严格来说,在 JavaScript 中不可能真正删除任何内容。 delete 运算符既不删除对象也不释放内存。相反,它将其操作数设置为 undefined 并操作父对象,以便成员消失。

        let parent = {
            member: { str: "Hello" }
        };
        let secondref = parent.member;
        
        delete parent.member;
        parent.member;        // undefined
        secondref;            // { str: "Hello" }
        

        对象没有被删除。只有参考是。只释放内存 当对对象的所有引用都被删除时,由垃圾收集器处理。

        另一个重要的警告是delete 运算符不会为您重新组织结构,其结果可能看起来违反直觉。例如,删除数组索引会在其中留下一个“洞”。

        let array = [0, 1, 2, 3]; // [0, 1, 2, 3]
        delete array[2];          // [0, 1, empty, 3]
        

        这是因为数组对象。所以索引和键是一样的。

        let fauxarray = {0: 1, 1: 2, length: 2};
        fauxarray.__proto__ = [].__proto__;
        fauxarray.push(3);
        fauxarray;                // [1, 2, 3]
        Array.isArray(fauxarray); // false
        Array.isArray([1, 2, 3]); // true
        

        JavaScript 中不同的内置函数以不同的方式处理带有孔的数组。

        • for..in 语句将完全跳过空索引。

        • 一个幼稚的for 循环将为索引处的值生成undefined

        • 任何使用Symbol.iterator 的方法都会为索引处的值返回undefined

        • forEachmapreduce 只会跳过丢失的索引,但不会删除它

        例子:

        let array = [1, 2, 3]; // [1,2,3]
        delete array[1];       // [1, empty, 3]
        array.map(x => 0);     // [0, empty, 0]
        

        因此,delete 运算符不应用于从数组中删除元素的常见用例。数组有专门的移除元素和重新分配内存的方法:Array#splice()Array#pop

        Array#splice(start[, deleteCount[, item1[, item2[, ...]]]])

        Array#splice 改变数组,并返回所有删除的索引。 deleteCount 元素从索引start 中删除,item1, item2... itemN 从索引start 插入到数组中。如果 deleteCount 被省略,则 startIndex 中的元素将被删除到数组的末尾。

        let a = [0,1,2,3,4]
        a.splice(2,2) // returns the removed elements [2,3]
        // ...and `a` is now [0,1,4]
        

        Array.prototype 上还有一个名称相似但不同的函数:Array#slice

        数组#slice([begin[, end]])

        Array#slice 是非破坏性的,它返回一个新数组,其中包含从startend 的指示索引。如果未指定 end,则默认为数组的末尾。如果end 是正数,它指定要停止的从零开始的非包含 索引。如果end 是负数,它通过从数组末尾倒数指定要停止的索引(例如,-1 将省略最终索引)。如果end <= start,则结果为空数组。

        let a = [0,1,2,3,4]
        let slices = [
            a.slice(0,2),
            a.slice(2,2),
            a.slice(2,3),
            a.slice(2,5) ]
        
        //   a           [0,1,2,3,4]
        //   slices[0]   [0 1]- - -   
        //   slices[1]    - - - - -
        //   slices[2]    - -[3]- -
        //   slices[3]    - -[2 4 5]
        

        数组#pop

        Array#pop 从数组中删除最后一个元素,并返回该元素。此操作更改数组的长度。相反的操作是push

        数组#shift

        Array#shift 类似于pop,除了它删除了第一个元素。相反的操作是unshift

        【讨论】:

          【解决方案6】:

          Spread Syntax (ES6)

          要完成Koen's answer,如果您想使用展开语法删除动态变量,您可以这样做:

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

          扩展答案?

          有几种常用的方法可以从对象中删除属性。
          每个都有自己的优点和缺点 (check this performance comparison):

          Delete Operator

          它可读且简短,但是,如果您在大量对象上进行操作,它可能不是最佳选择,因为它的性能未优化。

          delete obj[key];
          

          Reassignment

          它比delete 快两倍以上,但是该属性没有被删除并且可以迭代。

          obj[key] = null;
          obj[key] = false;
          obj[key] = undefined;
          

          Spread Operator

          这个ES6 运算符允许我们返回一个全新的对象,不包括任何属性,而不改变现有对象。缺点是它的性能比上述更差,不建议在需要一次删除许多属性时使用。

          { [key]: val, ...rest } = obj;
          

          【讨论】:

          • 这不是删除属性,而是创建一个浅拷贝,而不是跨指定的键和值进行复制。这是一个非常大的区别。
          【解决方案7】:

          另一种选择是使用Underscore.js 库。

          注意_.pick()_.omit() 都返回对象的副本,而不是直接修改原始对象。将结果分配给原始对象应该可以解决问题(未显示)。

          参考:link _.pick(object, *keys)

          返回对象的副本,过滤后仅包含 白名单键(或有效键数组)。

          var myJSONObject = 
          {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
          
          _.pick(myJSONObject, "ircEvent", "method");
          => {"ircEvent": "PRIVMSG", "method": "newURI"};
          

          参考:link _.omit(object, *keys)

          返回对象的副本,过滤以省略 列入黑名单的键(或键数组)。

          var myJSONObject = 
          {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
          
          _.omit(myJSONObject, "regex");
          => {"ircEvent": "PRIVMSG", "method": "newURI"};
          

          对于数组,_.filter()_.reject() 可以以类似的方式使用。

          【讨论】:

            【解决方案8】:

            克隆没有属性的对象:

            例如:

            let object = { a: 1, b: 2, c: 3 };
            

            我们需要删除a

            1. 使用显式属性键

              const { a, ...rest } = object;
              object = rest;
              
            2. 使用可变道具键

              const propKey = 'a';
              const { [propKey]: propValue, ...rest } = object;
              object = rest;
              
            3. 一个很酷的箭头函数?:

              const removeProperty = (propKey, { [propKey]: propValue, ...rest }) => rest;
              
              object = removeProperty('a', object);
              
            4. 对于多个属性

              const removeProperties = (object, ...keys) => (keys.length ? removeProperties(removeProperty(keys.pop(), object), ...keys) : object);
              

            用法

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

            或者

            const propsToRemove = ['a', 'b']
            object = removeProperties(object, ...propsToRemove) // result => { c: 3 }
            

            【讨论】:

              【解决方案9】:

              您在问题标题中使用的术语,从 JavaScript 对象中删除属性,可以用一些不同的方式来解释。一种是从整个内存和对象键列表中删除它,另一种是从对象中删除它。正如在其他一些答案中提到的那样,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 语句会阻止创建的对象被删除。

              这意味着在这种情况下您将无法删除该对象,因为您已通过 var 语句创建了 regex 变量,如果您这样做了:

              delete regex; //False
              

              结果将是false,这意味着您的删除语句没有按预期执行。但是,如果您之前没有创建该变量,并且您只有 myOtherObject["regex"] 作为您的最后一个现有引用,您可以通过删除它来做到这一点:

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

              换句话说,只要代码中没有指向该对象的引用,JavaScript 对象就会被终止。


              更新:

              感谢@AgentME:

              在删除之前将属性设置为 null 不会完成 任何东西(除非对象已被 Object.seal 和 删除失败。通常情况并非如此,除非您特别指定 试试)。

              如需了解Object.seal的更多信息:Object.seal()

              【讨论】:

                【解决方案10】:

                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 函数(以及delete operator)在尝试删除它的任何属性时返回false。如果属性是可配置的,它返回true,即使属性不存在。

                deletedeleteProperty 的区别在于使用严格模式时:

                "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
                

                【讨论】:

                  【解决方案11】:

                  假设您有一个如下所示的对象:

                  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 也会弄乱您的索引。

                  因此,从对象中删除值时,请始终首先考虑您是在处理对象属性还是在处理数组值,并据此选择合适的策略。

                  如果您想对此进行试验,可以使用this Fiddle 作为起点。

                  【讨论】:

                    【解决方案12】:

                    我个人使用Underscore.jsLodash 进行对象和数组操作:

                    myObject = _.omit(myObject, 'regex');
                    

                    【讨论】:

                      【解决方案13】:

                      使用 delete 方法是最好的方法,根据 MDN 的描述,删除操作符从对象中删除一个属性。所以你可以简单地写:

                      delete myObject.regex;
                      // OR
                      delete myObject['regex'];
                      

                      delete 运算符从对象中删除给定的属性。上 删除成功返回true,否则返回false。 但是,请务必考虑以下情况:

                      • 如果您要删除的属性不存在,请删除 不会有任何效果,会返回 true
                      • 如果对象的原型上存在同名属性 链,那么,在删除之后,该对象将使用来自 原型链(也就是说,delete只对自己有影响 属性)。
                      • 任何用 var 声明的属性都不能从全局作用域中删除 或来自函数的范围。
                      • 因此,delete 无法删除全局范围内的任何函数(无论这是函数定义的一部分还是函数(表达式)。
                      • 作为对象一部分的函数(除了
                        全局作用域)可以用 delete 删除。
                      • 任何用 let 或 const 声明的属性都不能从定义它们的范围中删除。无法删除不可配置的属性。这包括内置对象(如 Math、Array、Object)的属性以及使用 Object.defineProperty() 等方法创建为不可配置的属性。

                      下面的sn-p再给出一个简单的例子:

                      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

                      【讨论】:

                        【解决方案14】:

                        另一种解决方案,使用 Array#reduce

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

                        【讨论】:

                          【解决方案15】:

                          这里有很多很好的答案,但我只想指出,在 JavaScript 中使用 delete 删除属性时,首先检查该属性是否存在以防止错误通常是明智的。

                          例如

                          var obj = {"property":"value", "property2":"value"};
                          
                          if (obj && obj.hasOwnProperty("property2")) {
                            delete obj.property2;
                          } else {
                            //error handling
                          }
                          

                          由于 JavaScript 的动态特性,经常出现您根本不知道属性是否存在的情况。在 && 之前检查 obj 是否存在还可以确保您不会因为在未定义的对象上调用 hasOwnProperty() 函数而引发错误。

                          很抱歉,如果这没有添加到您的特定用例中,但我相信这是一个很好的设计,可以在管理对象及其属性时进行调整。

                          【讨论】:

                            【解决方案16】:

                            这篇文章很老了,我觉得它很有帮助,所以我决定分享我写的 unset 函数,以防其他人看到这篇文章并想为什么它不像 PHP 的 unset 函数那么简单。

                            编写这个新的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"}

                            【讨论】:

                              【解决方案17】:

                              试试下面的方法。将Object 属性值分配给undefined。然后stringify对象和parse

                               var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
                              
                              myObject.regex = undefined;
                              myObject = JSON.parse(JSON.stringify(myObject));
                              
                              console.log(myObject);

                              【讨论】:

                                【解决方案18】:

                                使用ramda#dissoc你会得到一个没有regex属性的新对象:

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

                                你也可以使用其他函数来达到同样的效果——省略、选择、...

                                【讨论】:

                                  【解决方案19】:

                                  有几种方法可以从对象中删除属性:

                                  1. 使用点属性访问器删除

                                  const myObject = {
                                    "ircEvent": "PRIVMSG",
                                    "method": "newURI",
                                    "regex": "^http://.*",
                                  };
                                  
                                  delete myObject.regex;
                                  console.log(myObject);
                                  1. 使用方括号属性访问器删除

                                  const myObject = {
                                        "ircEvent": "PRIVMSG",
                                        "method": "newURI",
                                        "regex": "^http://.*",
                                      };
                                  
                                  delete myObject['regex'];
                                  console.log(myObject);
                                  // or
                                  const name = 'ircEvent';
                                  delete myObject[name];
                                  console.log(myObject);
                                  1. 替代选项,但在不改变原始对象的情况下以不可变的方式使用对象解构和休息语法。

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

                                  【讨论】:

                                    【解决方案20】:

                                    使用Lodash

                                    import omit from 'lodash/omit';
                                    
                                    const prevObject = {test: false, test2: true};
                                    // Removes test2 key from previous object
                                    const nextObject = omit(prevObject, 'test2');
                                    

                                    使用 Ramda

                                    R.omit(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, c: 3}
                                    

                                    【讨论】:

                                    • 很奇怪。您的代码 _.omit(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); 对我不起作用,但 _.omit({a: 1, b: 2, c: 3, d: 4}, ['a', 'd']); 确实起作用。
                                    【解决方案21】:

                                    如果你想删除一个深深嵌套在对象中的属性,那么你可以使用以下递归函数,并将属性的路径作为第二个参数:

                                    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: {}}}
                                    

                                    【讨论】:

                                      【解决方案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"];
                                              }
                                          }
                                      );

                                      【讨论】:

                                        【解决方案23】:

                                        这是一种 ES6 轻松删除条目的方法:

                                        let myObject = {
                                          "ircEvent": "PRIVMSG",
                                          "method": "newURI",
                                          "regex": "^http://.*"
                                        };
                                        
                                        const removeItem = 'regex';
                                        
                                        const { [removeItem]: remove, ...rest } = myObject;
                                        
                                        console.log(remove); // "^http://.*"
                                        console.log(rest); // Object { ircEvent: "PRIVMSG", method: "newURI" }

                                        【讨论】:

                                          【解决方案24】:

                                          Dan's assertion'delete' 非常慢,他发布的基准受到质疑。所以我自己在 Chrome 59 中进行了测试。看起来“删除”确实慢了大约 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
                                          

                                          请注意,我特意在一个循环周期中执行了多个“删除”操作,以尽量减少其他操作造成的影响。

                                          【讨论】:

                                            【解决方案25】:

                                            JavaScript 中的属性删除

                                            此页面上提供了许多不同的选项,不是因为大多数选项都是错误的——或者因为答案是重复的——而是因为适当的技术取决于你所处的情况以及你和任务的目标/或者你的团队正在努力实现。要明确回答您的问题,您需要知道:

                                            1. 您要定位的 ECMAScript 版本
                                            2. 要删除属性的对象类型范围以及需要能够省略的属性名称类型(仅限字符串?符号?从任意对象映射的弱引用?这些都是 JavaScript 中的属性指针类型多年来)
                                            3. 您和您的团队使用的编程精神/模式。您喜欢函数式方法并且在您的团队中禁止使用变异,还是使用狂野的西部变异面向对象技术?
                                            4. 您是希望在纯 JavaScript 中实现这一目标,还是愿意并能够使用第 3 方库?

                                            一旦这四个查询得到回答,为了满足您的目标,JavaScript 中基本上有四种“属性删除”类别可供选择。它们是:

                                            可变对象属性删除,不安全

                                            当您想要保留/继续使用原始引用并且不在代码中使用无状态功能原则时,此类别用于对对象字面量或对象实例进行操作。此类别中的示例语法:

                                            'use strict'
                                            const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true }
                                            delete iLikeMutatingStuffDontI[Symbol.for('amICool')] // true
                                            Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false })
                                            delete iLikeMutatingStuffDontI['amICool'] // throws
                                            

                                            此类别是最古老、最直接且受支持最广泛的财产移除类别。除了字符串之外,它还支持 Symbol 和数组索引,并且适用于除第一个版本之外的所有 JavaScript 版本。但是,它是可变的,它违反了一些编程原则并具有性能影响。在 non-configurable properties in strict mode 上使用时也可能导致未捕获的异常。

                                            基于 Rest 的字符串属性省略

                                            当需要非可变方法并且您不需要考虑符号键时,此类别适用于在较新的 ECMAScript 风格中对普通对象或数组实例进行操作:

                                            const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true }
                                            const { name, ...coolio } = foo // coolio doesn't have "name"
                                            const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn't account for Symbols :(
                                            

                                            可变对象属性删除,安全

                                            当您想要保留/继续使用原始引用同时防止在不可配置的属性上引发异常时,此类别用于对对象字面量或对象实例进行操作:

                                            'use strict'
                                            const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true }
                                            Reflect.deleteProperty(iLikeMutatingStuffDontI, Symbol.for('amICool')) // true
                                            Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false })
                                            Reflect.deleteProperty(iLikeMutatingStuffDontI, 'amICool') // false
                                            

                                            此外,虽然就地改变对象不是无状态的,但您可以使用 Reflect.deleteProperty 的函数特性来执行部分应用程序和其他 delete 语句无法实现的函数技术。

                                            基于语法的字符串属性省略

                                            当需要非可变方法并且您不需要考虑符号键时,此类别适用于在较新的 ECMAScript 风格中对普通对象或数组实例进行操作:

                                            const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true }
                                            const { name, ...coolio } = foo // coolio doesn't have "name"
                                            const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn't account for Symbols :(
                                            

                                            基于库的属性省略

                                            此类别通常允许更大的功能灵活性,包括考虑符号和在一个语句中省略多个属性:

                                            const o = require("lodash.omit")
                                            const foo = { [Symbol.for('a')]: 'abc', b: 'b', c: 'c' }
                                            const bar = o(foo, 'a') // "'a' undefined"
                                            const baz = o(foo, [ Symbol.for('a'), 'b' ]) // Symbol supported, more than one prop at a time, "Symbol.for('a') undefined"
                                            

                                            【讨论】:

                                              【解决方案26】:

                                              您可以使用如下过滤器

                                              var myObject = {
                                                  "ircEvent": "PRIVMSG",
                                                  "method": "newURI",
                                                  "regex": "^http://.*"
                                              };
                                              
                                              // Way 1
                                              
                                              let filter1 = {}
                                                Object.keys({...myObject}).filter(d => {
                                                if(d !== 'regex'){
                                                  filter1[d] = myObject[d];
                                                }
                                              })
                                              
                                              console.log(filter1)
                                              
                                              // Way 2
                                              
                                              let filter2 = Object.fromEntries(Object.entries({...myObject}).filter(d =>
                                              d[0] !== 'regex'
                                              ))
                                              
                                              console.log(filter2)

                                              【讨论】:

                                              • 但是 filter() 方法创建了一个数组,其中填充了所有通过测试的数组元素,因此过滤器的唯一目的是减少并创建一个新数组
                                              • 是的,但这只有在您使用过滤器的返回值时有用in 作为它的参数,但如果这些事情在这里完成,则没有,所以它的唯一目的是迭代数组元素,这就是 forEach 的用途
                                              • 你可以改为let filter = Object.fromEntries(Object.entries(myObject).filter(d =&gt; d !== 'regex' ))
                                              【解决方案27】:

                                              @johnstock,我们还可以使用 JavaScript 的原型设计概念向对象添加方法,以删除调用对象中可用的任何传递的键。

                                              感谢以上答案。

                                              var myObject = {
                                                "ircEvent": "PRIVMSG",
                                                "method": "newURI",
                                                "regex": "^http://.*"
                                              };
                                              
                                              // 1st and direct way 
                                              delete myObject.regex; // delete myObject["regex"]
                                              console.log(myObject); // { ircEvent: 'PRIVMSG', method: 'newURI' }
                                              
                                              // 2 way -  by using the concept of JavaScript's prototyping concept
                                              Object.prototype.removeFromObjectByKey = function(key) {
                                                // If key exists, remove it and return true
                                                if (this[key] !== undefined) {
                                                  delete this[key]
                                                  return true;
                                                }
                                                // Else return false
                                                return false;
                                              }
                                              
                                              var isRemoved = myObject.removeFromObjectByKey('method')
                                              console.log(myObject) // { ircEvent: 'PRIVMSG' }
                                              
                                              // More examples
                                              var obj = {
                                                a: 45,
                                                b: 56,
                                                c: 67
                                              }
                                              console.log(obj) // { a: 45, b: 56, c: 67 }
                                              
                                              // Remove key 'a' from obj
                                              isRemoved = obj.removeFromObjectByKey('a')
                                              console.log(isRemoved); //true
                                              console.log(obj); // { b: 56, c: 67 }
                                              
                                              // Remove key 'd' from obj which doesn't exist
                                              var isRemoved = obj.removeFromObjectByKey('d')
                                              console.log(isRemoved); // false
                                              console.log(obj); // { b: 56, c: 67 }

                                              【讨论】:

                                                【解决方案28】:

                                                我已经使用Lodash "unset" 使其也适用于嵌套对象...只是这需要编写小逻辑来获取 omit 方法所期望的属性键的路径.

                                                1. 以数组形式返回属性路径的方法

                                                var a = {"bool":{"must":[{"range":{"price_index.final_price":{"gt":"450", "lt":"500"}}}, {"bool":{"should":[{"term":{"color_value.keyword":"Black"}}]}}]}};
                                                
                                                function getPathOfKey(object,key,currentPath, t){
                                                    var currentPath = currentPath || [];
                                                
                                                    for(var i in object){
                                                        if(i == key){
                                                            t = currentPath;
                                                        }
                                                        else if(typeof object[i] == "object"){
                                                            currentPath.push(i)
                                                            return getPathOfKey(object[i], key,currentPath)
                                                        }
                                                    }
                                                    t.push(key);
                                                    return t;
                                                }
                                                document.getElementById("output").innerHTML =JSON.stringify(getPathOfKey(a,"price_index.final_price"))
                                                <div id="output">
                                                
                                                </div>
                                                1. 然后只需使用Lodash unset 方法从对象中删除属性。

                                                var unset = require('lodash.unset');
                                                unset(a, getPathOfKey(a, "price_index.final_price"));

                                                【讨论】:

                                                  【解决方案29】:

                                                  let myObject = {
                                                      "ircEvent": "PRIVMSG",
                                                      "method": "newURI",
                                                      "regex": "^http://.*"
                                                  };
                                                  
                                                  
                                                  obj = Object.fromEntries(
                                                      Object.entries(myObject).filter(function (m){
                                                          return m[0] != "regex"/*or whatever key to delete*/
                                                      }
                                                  ))
                                                  
                                                  console.log(obj)

                                                  您也可以使用Object.entries 将对象视为a2d 数组,并像在普通数组中一样使用拼接删除元素,或者像数组一样简单地过滤对象,然后分配将重构对象还原为原始变量

                                                  【讨论】:

                                                    【解决方案30】:

                                                    如果您不想修改原始对象。

                                                    删除属性而不改变对象

                                                    如果可变性是一个问题,您可以通过复制旧对象的所有属性来创建一个全新的对象,但要删除的属性除外。

                                                    let myObject = {
                                                      "ircEvent": "PRIVMSG",
                                                      "method": "newURI",
                                                      "regex": "^http://.*"
                                                    };
                                                    
                                                    let prop = 'regex';
                                                    const updatedObject = Object.keys(myObject).reduce((object, key) => {
                                                      if (key !== prop) {
                                                        object[key] = myObject[key]
                                                      }
                                                      return object
                                                    }, {})
                                                    
                                                    console.log(updatedObject);

                                                    【讨论】:

                                                      猜你喜欢
                                                      • 2010-09-17
                                                      • 2011-05-09
                                                      • 2011-01-16
                                                      • 2012-02-16
                                                      • 2021-09-29
                                                      相关资源
                                                      最近更新 更多