我如何从JavaScript对象中移除一个属性?

假设我创建一个对象如下:

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

如何删除属性regex最终以new myObject结束的最佳方式如下?

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

喜欢这个:

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

操作员delete出乎意料地慢!

看看基准

删除是删除对象的属性没有任何剩菜剩下的唯一真正的方法,但它的工作速度比其“替代”,设置object[key] = undefined 慢100倍

这个选择不是这个问题的正确答案! 但是,如果你小心使用它,你可以大大加快一些算法。 如果您在循环中使用delete ,并且在性能方面存在问题,请阅读详细解释。

什么时候应该使用delete ,何时将value设置为undefined

一个对象可能被看作是一组键值对。 我称之为'价值'是一个原始的或对其他对象的引用,连接到'钥匙'。

当你将结果对象传递给你没有控制权的代码时(或者当你不确定你的团队或你自己时) ,使用delete

从哈希映射中删除密钥

 var obj = {
     field: 1     
 };
 delete obj.field;

如果您关心性能,请使用设置为undefined 。 它可以大大提高你的代码。

关键在于它在hashmap中的位置 ,只有值被替换为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] = undefineddelete obj[prop]更快时,另一个重要的考虑是obj[prop] = undefined可能并不总是合适的。 delete obj[prop]obj删除prop并从内存中删除它,而obj[prop] = undefined只是简单地将prop的值设置为undefined ,使prop保留在内存中。 因此,在创建和删除许多密钥的情况下,使用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个插槽仅设置为未定义,这会使它们挂在内存中。 继续,尝试在控制台上运行上面的代码并亲自查看。 在强制出现内存不足错误之后,尝试再次运行它,除非使用以下版本的使用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

但是,多态数组有两个主要的不可修复问题:

  • 它们速度慢,内存效率低下。 当访问特定索引时,浏览器不必为数组获取全局类型,而必须按每个索引获取类型,从而每个索引都存储其类型的其他元数据。
  • 一旦多态,总是多态的。 当数组变为多态时,多态性不能在Webkit浏览器中撤消。 因此,即使您将多态数组恢复为非多态,它仍将作为多态数组存储在浏览器中。
  • 人们可以将多态性比喻为吸毒成瘾。 乍一看,它看起来非常有利可图:漂亮的漂亮蓬松的代码。 然后,编码人员将他们的数组引入多态性药物。 瞬间,多态阵列变得效率较低,并且因为它被麻醉,它永远不会像以前那样高效。 为了将这种情况与现实生活联系起来,可卡因上的某个人甚至可能无法操作简单的门把手,更不用说能够计算出PI的数字。 同样,多态性药物的阵列不可能像单形阵列一样有效。

    但是,药物旅行类似于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 。 因此,应尽可能使用相应类型的对象,以免意外引起多态性。 一个这样的人可以使用下面的列表作为通用参考来让他们走。 但是,请不要明确地使用下面的想法。 相反,请使用适合您的代码的任何方法。

  • 当使用键入布尔原语的数组/变量时,请使用falseundefined作为空值。 虽然避免不必要的多态性是好事,但重写所有代码以显式禁止它可能会导致性能下降。 使用常见的判断!
  • 当使用键入数字基元的数组/变量时,使用0作为空值。 请注意,内部有两种类型的数字:快速整数(包括2147483647到-2147483648)和慢浮点双精度(包括NaNInfinity在内的任何其他类型)。 当一个整数降级到double时,它不能被提升回一个整数。
  • 当使用键入字符串基元的数组/变量时,使用""作为空值。
  • 使用符号时,请等待,为什么使用符号?!?! 性能不佳的符号是不好的。 所有编程为使用符号的程序都可以重新编程为不使用符号,从而在没有符号的情况下生成更快的代码。 符号实际上只是超低效的元糖。
  • 在使用其他任何东西时,请使用null
  • 但是,请注意! 现在不要突然开始使用所有现有的代码,因为它可能会破坏以前存在的代码和/或引入奇怪的错误。 相反,从一开始就需要实施这样一种有效的做法,并且在转换已有的代码时,建议您将与之相关的所有行都加倍,三倍,四倍检查,因为试图将旧代码升级到这种新的做法可能是因为它是有价值的。


    var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
        
    delete myJSONObject.regex;
    
    console.log ( myJSONObject.regex); // logs: undefined
    链接地址: http://www.djcxy.com/p/83.html

    上一篇: How do I remove a property from a JavaScript object?

    下一篇: How do I push a new local branch to a remote Git repository and track it too?