两者中的任何一个有实质性的区别吗?
delete a.x;
与
a.x = undefined;
哪里
a = {
x: 'boo'
};
可以说它们相等吗?
(我没有考虑诸如“ V8喜欢不使用delete更好的东西”之类的东西)
两者中的任何一个有实质性的区别吗?
delete a.x;
与
a.x = undefined;
哪里
a = {
x: 'boo'
};
可以说它们相等吗?
(我没有考虑诸如“ V8喜欢不使用delete更好的东西”之类的东西)
Answers:
它们不相等。主要区别在于设置
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将允许它向上扩展原型链,而将值设置为undefined将不会在链接的原型中寻找属性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也将不同。
undefined,则最好只检查if (a.x),除非它是用于数字且0是有效的
解释这个问题:
是
delete a.x和a.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'
delete允许其沿原型链上升的要点
是,有一点不同。如果使用delete a.xx,则不再是a的属性,但是如果使用a.x=undefinedx是属性,但其值未定义。
我敢肯定,你可以看到之间的差异var o1 = {p:undefined};和var o2 = {};。
在这两种情况下,o.p将undefined但在第一种情况下,这是因为这是值和在第二种情况下,因为没有价值。
delete是可让您从o1(或为其p属性分配值的另一个对象)进行以下操作的运算符o2:delete o1.p;。
只需通过undefined为属性分配一个值(在此示例中为该值,但可以是其他值)即可完成反向操作o1.p = undefined;。
所以不,它们不是等效的。
delete o.p; 将
p从对象中删除该属性(如果有一个)
否则不做任何事情
o.p = undefined; 将
p如果对象尚不存在,请向其添加属性,并将其值设置为undefined
只需更改属性的值(如果对象已经拥有)
从性能的角度来看,这delete是不好的,因为它会修改对象的结构(就像在构造函数中未初始化新属性一样,它就像添加新属性一样)。
而将值设置undefined为也会释放内容,但不强制修改结构。
对象只是树的表示,这意味着在内存中,根指向存储该对象的键的各种存储位置。并且该位置指向存储该键的实际值的另一个位置,或者存储子键的位置,或者存储数组值的位置。
当您使用delete从对象中删除任何键时,实际上它会删除该键与其父对象之间的链接,并且键的存储位置及其值将被释放以存储其他信息。
当您尝试通过将undefined设置为键值来删除任何键时,那么您只是在设置其值,而不是删除该键。这意味着密钥存储位置仍与它的父对象和未定义密钥的值链接。
使用undefined而不是delete关键字是一个坏习惯,因为它不会释放该键的内存位置。
即使键不存在,并且您将其设置为undefined,该键也将使用value创建undefined。
例如
var a = {};
a.d = undefined;
console.log(a); // this will print { d: undefined }
删除不能与继承的属性一起使用,因为该属性不是该子对象的一部分。
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/...
使用数组而不是对象,我可以展示删除所使用的堆内存少于未定义的堆内存。
例如,此代码不会完成:
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项目(而不是仅将其设置为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我从未见过有人提及的地方。