javascript - 如何移除一个对象的某个属性

标签 IT工具网 javascript

原问题:Remove property from JavaScript object

如何移除一个JavaScript对象?

首先分析问题:

  • JavaScript对象的结构都是JSON
  • 问题转化成移除一个JSON对象的属性

再由具体到抽象,尝试三个层面来解决这个问题: * JSON Object Property,查ECMAScript JSON规范 -> * Object Property:查ECMAScript Object规范 -> * Property:因为一个对象的属性仍然是对象,所以仍然查ECMAScript Object规范

根据ECMAScript中对JSON对象的定义,它只有两个方法:parse() && stringify(),放弃。

根据ECMAScript的Working with Objects,文档倒数第二小节正好讲得就是Deleting properties: > 可以使用delete运算符来删除一个对象的非继承属性。

因此,我们就从delete运算符入手。 * delete运算符 * 语法 * 运算结果 * 谨慎使用delete * 为什么delete很慢 * delete的替代方案

delete

来看看delete运算符的定义: > delete运算符用来删除一个对象、一个对象属性或者数组中的某个元素。

delete语法

示例:

delete objectName;
delete objectName.property;
delete objectName[index];
delete property; // legal only within a with statement

delete还能用来删除一个全局变量,如果该变量不是使用var声明的。(区分*variable declaration*和*property assignment*)

示例:

var GLOBAL_OBJECT = this;

/* create global property via variable declaration; property has DontDelete */
var foo = 1;

/* create global property via undeclared assignment; property has no DontDelete */
bar = 2;

console.log(foo);
delete foo; // false
console.log(typeof foo); // "number"

console.log(bar);
delete bar; // true
console.log(typeof bar); // "undefined"

delete结果

如果delete操作成功,它将会把操作数的值置为undefined,然后返回true。否则返回false

注意,使用delete删除一个数组array的元素i后,array[i]元素就不存在了。

var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
delete trees[3];
if (trees[3] || 3 in trees) { // undefined || false
  // this does not get executed
}

因此,如果你只是想删除array[i]的值,同时保持i元素在array中的位置,就不能使用delete,而应该直接对array[i]赋值。

var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
trees[3] = undefined;
if (trees[3] || 3 in trees) { // undefined || true
  // this gets executed
}

谨慎使用delete

因为delete操作的效率很低。

为什么delete很慢

因为JavaScript语言的动态属性: > 可以随时随地向对象添加、删除属性。

因此大多数JavaScript引擎对Object的实现时,采用的是*dictionary-like data structure*,比如hashmap。采用这种数据结构的一大弊端就是*dictionary lookup*是非常低效的,即读取速度慢。

为了提高读取对象属性的速度,V8引擎使用了*hidden class*技术,其基本思想就是:空间换时间。 * 每个对象都对应生成一个hidden class * 生成属性表,使用Java/Smalltalk等静态语言对于对象属性的编译方式:fixed offset * 每次增加或删除对象属性的时候,更新其hidden class,这称作transition

V8 hidden class的具体细节,请参考:Fast Property Access - V8 Design

注意第三条,每次增加或删除属性的操作,都会引发hidden class transition。如果一个对象的属性很多,那么这个transition操作将会很耗资源。

而JavaScript的prototype继承机制,使得对象属性的数量很容易就达到较大的数字。因此,尽量避免使用delete

delete的替代方案

delete类似的方案是undefined/null的赋值操作。

根据它们的性能对比测试可以看出,使用undefined/null的赋值操作的效率,是delete操作的十倍以上。对于一些计算密集的算法,尤其需要注意。

相关文章:

如何创建泛型java数组

javascript - scrollIntoView() 没有将节点滚动到树的顶部

javascript - 我如何知道用户是否已登录

javascript - 如何使用 Cloudinary Angular 生成 url?

如何克隆Clone一个JavaScript对象

java如何从文件里读取字符串

java finally代码块总会被执行么

如何在classpath中设置多个jar包

javascript - 弹出菜单的 slideToggle

javascript - 如何使用 Jquery/Javascript/css 在每次点击时动态旋转圆圈?