【问题标题】:delete a.x vs a.x = undefined删除 a.x vs a.x = undefined
【发布时间】:2013-02-04 17:27:16
【问题描述】:

做这些有什么实质性的区别吗?

delete a.x;

a.x = undefined;

在哪里

a = {
    x: 'boo'
};

可以说它们是等价的吗?

(我没有考虑像 "V8 likes not using delete better" 这样的东西)

【问题讨论】:

  • 删除操作符完全删除一个属性。将属性设置为 undefined 会删除该值。将属性设置为 null 会将值更改为 null 值。如果您愿意,可以在这里进行性能测试:jsperf.com/delete-vs-undefined-vs-null/3
  • @j08691 Nit:它不会删除该值。它分配undefined 作为值,它仍然是一个..
  • 你应该谈谈你为什么关心这个,然后答案才能迎合你的实际问题。

标签: javascript


【解决方案1】:

它们不等价。主要区别在于设置

a.x = undefined

表示a.hasOwnProperty("x") 仍将返回true,因此,它仍将显示在for in 循环和Object.keys()

delete a.x

表示a.hasOwnProperty("x")会返回false

它们的相同之处在于您无法通过测试来判断属性是否存在

if (a.x === undefined)

如果你试图确定一个属性是否存在,你不应该这样做,你应该总是使用

// If you want inherited properties
if ('x' in a)

// If you don't want inherited properties
if (a.hasOwnProperty('x'))

遵循原型链(由zzzzBov 提及)调用delete 将允许它沿原型链向上,而将值设置为未定义将不会在链中查找属性原型http://jsfiddle.net/NEEw4/1/

var obj = {x: "fromPrototype"};
var extended = Object.create(obj);
extended.x = "overriding";
console.log(extended.x); // overriding
extended.x  = undefined;
console.log(extended.x); // undefined
delete extended.x;
console.log(extended.x); // fromPrototype

删除继承的属性 如果您尝试删除的属性是继承的,delete 不会影响它。也就是说,delete 只删除对象本身的属性,而不是继承的属性。

var obj = {x: "fromPrototype"};
var extended = Object.create(obj);
delete extended.x;
console.log(extended.x); // Still fromPrototype

因此,如果您需要确保对象的值未定义,delete 在继承该属性时将不起作用,在这种情况下您必须将其设置(覆盖)为undefined。除非检查它的地方会使用hasOwnProperty,但假设所有检查它的地方都会使用hasOwnProperty 可能是不安全的

【讨论】:

  • "x" in a 也将返回 true 与前者,false 与后者。 Object.keys 的输出也会有所不同。
  • 你为什么说我不应该检查未定义?对我来说似乎很合理。
  • @Nico 因为这不会告诉您是否存在属性。我并不是说永远不要使用它。但是如果你检查的是undefined,你也可以只检查if (a.x),除非它是数字并且0是有效的
【解决方案2】:

解释问题:

delete a.xa.x = undefined 是否等效?

没有。

前者从变量中删除键,后者将键设置为undefined。这在迭代对象的属性以及使用 hasOwnProperty 时会有所不同。

a = {
    x: true
};
a.x = undefined;
a.hasOwnProperty('x'); //true
delete a.x;
a.hasOwnProperty('x'); //false

此外,当涉及原型链时,这将产生重大影响。

function Foo() {
    this.x = 'instance';
}
Foo.prototype = {
    x: 'prototype'
};
a = new Foo();
console.log(a.x); //'instance'

a.x = undefined;
console.log(a.x); //undefined

delete a.x;
console.log(a.x); //'prototype'

【讨论】:

  • +1 关于delete 允许它进入原型链的好点
【解决方案3】:

这个来自节点的 REPL 应该说明差异。

> a={ x: 'foo' };
{ x: 'foo' }
> for (var i in a) { console.log(i); };
x
undefined
> a.x=undefined;
undefined
> for (var i in a) { console.log(i); };
x
undefined
> delete a.x;
true
> for (var i in a) { console.log(i); };
undefined

【讨论】:

    【解决方案4】:

    名称有点混乱。 a.x = undefined 只是将属性设置为undefined,但属性仍然存在:

    > var a = {x: 3};
    > a.x = undefined;
    > a.constructor.keys(a)
    ["x"]
    

    delete 实际上删除了它:

    > var a = {x: 3};
    > delete a.x;
    > a.constructor.keys(a)
    []
    

    【讨论】:

      【解决方案5】:

      是的,有区别。 如果您使用delete a.x,则 x 不再是 a 的属性,但如果您使用 a.x=undefined,它是一个属性,但其值未定义。

      【讨论】:

        【解决方案6】:

        我相信您可以看出var o1 = {p:undefined};var o2 = {}; 之间的区别。

        在这两种情况下,o.p 将是 undefined,但在第一种情况下,这是因为这是 ,而在第二种情况下,因为 没有值 .

        delete 是一个运算符,可让您以这种方式从 o1(或另一个为其p 属性分配了值的对象)到o2delete o1.p;

        通过简单地为属性o1.p = undefined; 分配一个值(在此示例中为undefined,但它可以是其他值)来进行反向操作。

        所以,它们是不等价的。


        delete o.p;

        • 从对象中删除属性p(如果有的话)

        • 否则什么也不做

        o.p = undefined;

        • 如果对象还没有属性p,则将其值添加到undefined

        • 如果对象已经拥有该属性,只需更改它的值


        从性能的角度来看,delete不好,因为它修改了对象的结构(就像添加一个新属性,如果你没有在构造函数)。

        而将值设置为undefined 也会释放内容,但不会强制修改结构。

        【讨论】:

          【解决方案7】:

          对象只是一个树表示,这意味着在内存中,根指向存储该对象的键的各个内存位置。并且该位置指向存储该键的实际值的另一个位置,或存储子键的位置或存储数组值的位置。

          当您使用 delete 从对象中删除任何键时,实际上它会删除该键与其父对象之间的链接,并释放键及其值的内存位置以存储其他信息。

          当您尝试通过将 undefined 设置为其值来删除任何键时,您只是在设置其值,而不是删除该键。这意味着键的内存位置仍然与其父对象和未定义键的值相关联。

          使用 undefined 而不是 delete 关键字是一种不好的做法,因为它不会释放该键的内存位置。

          即使该键不存在,并且您将其设置为未定义,那么该键也将使用值 undefined 创建。

          例如

          var a = {};
          a.d = undefined;
          console.log(a); // this will print { d: undefined }
          

          delete 不能与继承的属性一起使用,因为该属性不是该子对象的一部分。

          【讨论】:

          • 请注意,较新的引擎希望您不要删除键,因为当您这样做时,引擎需要为其创建一个新类并在引用“类”的任何位置更新它。
          • @JuanMendes,请您提供任何参考。
          • Does using delete keyword affect v8 optimizations of an object? TL;DR as a general rule of thumb, using 'delete' makes thing slower.developers.google.com/v8/design To reduce the time required to access JavaScript properties, V8 does not use dynamic lookup to access properties. Instead, V8 dynamically creates hidden classes behind the scenes. In V8, an object changes its hidden class when a new property is added. ,最后是 smashingmagazine.com/2012/11/…
          【解决方案8】:

          如果a.x 是一个setter 函数,a.x = undefined 将调用该函数,而delete a.x 将不会调用该函数。

          【讨论】:

            【解决方案9】:

            使用数组而不是对象,我可以展示 delete 使用的堆内存比 undefined 少。

            例如,这段代码不会完成:

            let y = 1;
            let ary = [];
            console.log("Fatal Error Coming Soon");
            while (y < 4294967295)
            {
                ary.push(y);
                ary[y] = undefined;
                y += 1;
            }
            console(ary.length);
            

            它会产生这个错误:

            FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.
            

            所以,如您所见,undefined 实际上占用了堆内存。

            但是,如果您还 delete ary-item(而不是仅仅将其设置为 undefined),代码将慢慢完成:

            let x = 1;
            let ary = [];
            console.log("This will take a while, but it will eventually finish successfully.");
            while (x < 4294967295)
            {
                ary.push(x);
                ary[x] = undefined;
                delete ary[x];
                x += 1;
            }
            console.log(`Success, array-length: ${ary.length}.`);
            

            这些是极端的例子,但它们对delete 提出了一个观点,我没有看到任何人在任何地方提及。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-10-26
              • 2014-05-22
              • 2011-09-23
              • 2011-09-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多