原文:http://charlee.li/javascript-variables-and-delete-operator.html

刚刚看到一篇好文(原文链接), 对Javascript中的delete操作符分析得很透彻。在这里简单地介绍一下内容。

虽然是一个小小的delete操作符,其行为却异常复杂。

# Javascript的变量

实际上Javascript中,变量 = 对象属性,这是因为 Javascript 在执行脚本之前 会创建一个Global对象,所有的全局变量都是这个Global对象的属性, 执行函数时也会创建一个Activation对象,所有的局部变量都是这个Activation对象的属性。 如下例:

var global = 42;
this.global; // 42, 可以通过this来访问Global对象 this.global2 = 12;
global2; // function foo() {
var local = 36;
// 不过无法直接访问Activation,
// 因此无法通过 foo.local 的方式来访问local变量
}

delete操作符删除的对象

C++中也有delete操作符,它删除的是指针所指向的对象。例如:

// C++
class Object {
public:
Object *x;
} Object o;
o.x = new Object();
delete o.x; // 上一行new的Object对象将被释放

但Javascript的delete与C++不同,它不会删除o.x指向的对象,而是删除o.x属性本身。

// Javascript
var o = {};
o.x = new Object();
delete o.x; // 上一行new的Object对象依然存在
o.x; // undefined,o的名为x的属性被删除了

在实际的Javascript中,delete o.x之后,Object对象会由于失去了引用而被垃圾回收, 所以delete o.x也就“相当于”删除了o.x所指向的对象,但这个动作并不是ECMAScript标准, 也就是说,即使某个实现完全不删除Object对象,也不算是违反ECMAScript标准。

“删除属性而不是删除对象”这一点,可以通过以下的代码来确认。

var o = {};
var a = { x: 10 };
o.a = a;
delete o.a; // o.a属性被删除
o.a; // undefined
a.x; // 10, 因为{ x: 10 } 对象依然被 a 引用,所以不会被回收

另外,delete o.x 也可以写作 delete o[“x”],两者效果相同。

对变量执行delete的情况

由于变量也是 Global 或者是 Activation 对象的属性,所以对变量的delete操作也是同样的结果。

var global = 42;
delete global; // 删除Global.global function foo() {
var local = 36;
delete local; // 删除Activation.local
}

能删除的属性和不能删除的属性

并不是所有的属性都能被delete。例如,prototype中声明的属性就无法被delete:

function C() { this.x = 42; }
C.prototype.x = 12; var o = new C();
o.x; // 42, 构造函数中定义的o.x delete o.x;
o.x; // 12, prototype中定义的o.x,即使再次执行delete o.x也不会被删除

对象的预定义属性也无法删除。 可以认为这类属性带有DontDelete的特性。

var re = /abc/i;
delete re.ignoreCase;
re.ignoreCase; // true, ignoreCase无法删除

能删除的变量和不能删除的变量

通过var声明的变量和通过function声明的函数拥有DontDelete特性,无法被删除。

var x = 36;
delete x;
x; // 36, x没有被删除 y = 12;
delete y;
y; // undefined function foo() { return 42; }
delete foo;
foo(); //

但是有一点例外,就是通过 eval 执行的代码中,通过var声明的变量虽然与正常的var声明变量 同属于Global对象,但它们不具有DontDelete特性,能被删除。

eval("var x = 36;");
x; //
delete x;
x; // undefined

但是这也有一点例外,eval的代码中的函数内通过var定义的变量具有DontDelete,不能被删除。

eval("(function() { var x = 42; delete x; return x; })();");
// 返回 42

delete的返回值

delete是普通运算符,会返回true或false。规则为:当被delete的对象的属性存在并且拥有DontDelete时 返回false,否则返回true。 这里的一个特点就是,对象属性不存在时也返回true,所以返回值并非完全等同于删除成功与否。

function C() { this.x = 42; }
C.prototype.y = 12;
var o = new C(); delete o.x; // true
o.x; // undefined
"x" in o; // false
// o.x存在并且没有DontDelete,返回true delete o.y; // true
o.y; //
// o自身没有o.y属性,所以返回true
// 从这里也可以看到prototype链的存在,对象自身属性和prototype属性是不同的 delete o; // false
// Global.o拥有DontDelete特性所以返回false delete undefinedProperty; // true
// Global没有名为undefinedProperty的属性因此返回true delete 42; // true
// 42不是属性所以返回true。有的实现会抛出异常(违反ECMAScript标准) var x = 24;
delete x++; // true
x; //
// 被删除的是x++的返回值(24),不是属性,所以返回true

Javascript的变量与delete操作符的更多相关文章

  1. 你不知道的JavaScript(七)delete操作符

    JS中的delete操作符不是太常用,容易被忽略,它的作用很简单,用来删除对象的属性或方法. <script type="text/javascript"> var p ...

  2. javascript之delete操作符

    理解delete 理论 代码段的类型 执行上下文 活动对象 / 变量对象 属性的特性 内置属性与 DontDelete 未声明的赋值 Firebug的困惑 在eval中删除变量 浏览器兼容性 Geck ...

  3. [转]深入详解javascript之delete操作符

    最近重新温习JS,对delete操作符一直处于一知半解的状态,偶然发现一篇文章,对此作了非常细致深入的解释,看完有茅塞顿开的感觉,不敢独享,大致翻译如下. 原文地址:http://perfection ...

  4. JavaScript:变量对象(Variable Object)

    引言:在使用JavaScript编程的时候,避免不了声明函数和变量,但是我们很少知道解释器是如何并且在什么地方找到这些函数和变量的,我们在引用这些对象的时候究竟发生了什么? 对ECMAScript程序 ...

  5. js中的内部属性与delete操作符

    本文正式地址:http://www.xiabingbao.com/javascript/2015/08/03/javascript-delete-configurable 在讲解Configurabl ...

  6. js小知识 delete操作符

    说明:delete操作符用于删除对象的某个属性. 语法: delete object.property //删除 对象.属性 delete object['property'] //删除 对象['属性 ...

  7. JavaScript笔记:变量及其作用域

    一.变量的定义及声明 在javascript中变量仅仅是用来保存值的一个占位符而已,定义变量时要使用关键字var后跟一个变量名,如下所示: var message; //定义一个变量message,像 ...

  8. JavaScript 中变量、作用域和内存问题的学习

    这是我学习JavaScript的第二篇文章,之前做过几年的Java开发,发现JavaScript虽然也是面向对象的语言但是确实有很多不同之处.就本篇博客,主要学习总结一下最近学习到的JavaScrip ...

  9. javascript之变量、作用域、作用域链

    一.变量 javascript的变量是松散类型的,所谓松散类型就是说定义的变量可以用来保存任何类型的数据.定义变量时要使用var操作符后面跟变量名.这里的var是一个关键字,如果定义变量时省略了var ...

随机推荐

  1. RHEL7进程管理

    进程概念 名称 说明 程序 一组指令的集合 进程 程序的执行就是进程也可以把进程看成一个独立的程序在内存中有其对应的代码空间和数据空间,一个进程所拥有的数据和代码只属于自己进程是资源分配的基本单位,也 ...

  2. Android破解之Lic文件加密程序(首例)

    我不会写Android,这是我第一个破解Android的例子,耗时接近一天,希望大神不要见笑! 本程序为商业软件,不便发布APK程序. 不要给我发消息,我不得回,有问题,直接回帖就可以了. 准备工作 ...

  3. 参加2015年TOP100会议的零散笔记

    2015年出差很少,感到整个技术都已经荒废了,收到12月份TOP100的会议通知后,还是去充点电吧,不然心慌啊.对于软件大会这种大杂烩式的会议已经没有多少兴趣了,看看这个TOP100组织得有何不同? ...

  4. 基本完成了一个SEGY扫描程序

    利用Seismic.NET编写了一个SEG-Y文件的扫描程序,可以自动判断道头字中主测线号.横测线号.X坐标和Y坐标的位置,自动快速扫描地震数据体中的拐点坐标.10GB多的数据体几十秒全部扫描完成! ...

  5. Android底部TabHost API

    今天在项目中遇到了底部TabHost,顺便就写了一个底部TabHost的api继承即可使用非常简单,以下为源代码: 首先是自定义的TabHostActivity,如果要使用该TabHost继承该类即可 ...

  6. SPC.NET,为5年的开发做个结尾

    从08年到如今从事asp.net开发已五年,起初只是一个简单的喜好,想做个东西出来.于是SPC.NET的前生诞生了,直至今日. 不得不说,一个人开发一个软件是很辛苦的事情,以下是SPC.NET的一些特 ...

  7. sgu 104 Little shop of flowers 解题报告及测试数据

    104. Little shop of flowers time limit per test: 0.25 sec. memory limit per test: 4096 KB 问题: 你想要将你的 ...

  8. Spring中Template模式与callback的结合使用浅析

    Spring不论是与ibatis,还是与Hibernate的结合中,都使用到了Template模式与callback技术,来达到简化代码实现的目的.Template模式也即模板模式,用于对一些不太变化 ...

  9. 日志级别的选择:Debug、Info、Warn、Error还是Fatal

    原文地址:日志级别的选择:Debug.Info.Warn.Error还是Fatal 作者:shanshan2627 软件中总免不了要使用诸如 Log4net, Log4j, Tracer 等东东来写日 ...

  10. 编译时:virtual memory exhausted: Cannot allocate memory

    一.问题 当安装虚拟机时系统时没有设置swap大小或设置内存太小,编译程序会出现virtual memory exhausted: Cannot allocate memory的问题,可以用swap扩 ...