简述

我们都知道无法通过delete关键字针对变量和函数进行操作,而对于显示的对象属性声明却可以进行,这个原因需要深究到js的实现层上去,让我们跟随 Understanding delete 来探究一番,另外本文并不考虑浏览器的兼容性实现问题。

理论

为什么我们可以这样:

  var o = { x: 1 };
delete o.x; // true
o.x; // undefined

却无法这样

var x = 1;
delete x; // false
x; //

其实,这要涉及到执行上下文的概念,而每个执行上下文都对应一个变量对象VO,在全局上下文中VO就是全局对象window,在函数上下文中,VO也是活动地向AO,而在eval中的代码在执行时,其执行上下文也就是调用eval的上下文。

在上下文中定义的变量,函数声明以及函数的入参和AO特有的arguments对象等等,都属于VO(AO)的属性。而对于VO这样的实体对象而言,它也有自己的元数据,也就是在ES5中对象的数据特性:[[configurable]],[[enurable]],[[value]],[[writable]]。而对于VO的属性,默认的[[configurable]]是false,这样就无法针对这些变量使用delete操作。而对于显示的对象属性赋值,比如obj.name = “a”,对于name属性的[[configurable]]特性是true,因此可以删除。

var GLOBAL_OBJECT = this;

  /*  `foo` is a property of a Global object.
It is created via variable declaration and so has DontDelete attribute.
This is why it can not be deleted. */ var foo = 1;
delete foo; // false
typeof foo; // "number" /* `bar` is a property of a Global object.
It is created via function declaration and so has DontDelete attribute.
This is why it can not be deleted either. */ function bar(){}
delete bar; // false
typeof bar; // "function" /* `baz` is also a property of a Global object.
However, it is created via property assignment and so has no DontDelete attribute.
This is why it can be deleted. */ GLOBAL_OBJECT.baz = 'blah';
delete GLOBAL_OBJECT.baz; // true
typeof GLOBAL_OBJECT.baz; // "undefined"

另外,函数的length属性也是不可以删除的。

而对于未初始化的变量赋值,我们知道未初始化的变量默认为全局变量,VO的属性确定是在进入上下文阶段,因此未初始化变量并不会成为VO的属性,[[configurable]]仍未true,可以删除。

/* `foo` is created as a property with DontDelete */
function foo(){} /* Later assignments do not modify attributes. DontDelete is still there! */
foo = 1;
delete foo; // false
typeof foo; // "number" /* But assigning to a property that doesn't exist,
creates that property with empty attributes (and so without DontDelete) */ this.bar = 1;
delete bar; // true
typeof bar; // "undefined"

凡是都有例外,对于delete操作也难免。上述提到的第三种上下文--eval上下文,有个特殊的行为,就是在eval中声明的变量,函数可以在调用上下文中删除。

(function(){
eval('var foo = 1;');
foo; //
delete foo; // true
typeof foo; // "undefined" eval('var foo = 1;');
foo; //
delete foo; // true
typeof foo; // "undefined" })();

ES5严格模式

ES5的严格模式与上述提到的行为不同,它不准许delete删除函数入参,变量和函数,以及函数对象的length。删除未声明的 变量也会抛出语法错误SyntaxError。

(function(foo){

  "use strict"; // enable strict mode within this function

  var bar;
function baz(){} delete foo; // SyntaxError (when deleting argument)
delete bar; // SyntaxError (when deleting variable)
delete baz; // SyntaxError (when deleting variable created with function declaration) /* `length` of function instances has { [[Configurable]] : false } */ delete (function(){}).length; // TypeError delete i_dont_exist; // deleting undeclared variable (or in other words, unresolved Referece) throws SyntaxError
})();

总结

  • 需要知道有哪几种上下文,每个上下文对应一个VO
  • 上下文中定义的函数、变量、入参、arguments等都是VO的属性,[[configurable]]为false
  • eval上下文的特殊性
  • 未声明变量并不是VO的属性,[[configurable]]为true
  • 删除宿主对象属性时需小心,可能有意外发生,取决于js引擎的具体实现

Understanding delete的更多相关文章

  1. 深入理解JS的delete

    原文链接: Understanding delete原文作者: Kangax原文日期: 2010年01月10日 翻译日期: 2014年02月07日 翻译人员: 铁锚 !!!!!!!!草稿版本的翻译完成 ...

  2. 深入理解Delete(JavaScript)

    深入理解Delete(JavaScript) Delete  众所周知是删除对象中的属性. 但如果不深入了解delete的真正使用在项目中会出现非常严重的问题 (: Following 是翻译  ka ...

  3. javascript ES5 Object对象

    原文:http://javascript.ruanyifeng.com/stdlib/object.html 目录 概述 Object对象的方法 Object() Object.keys(),Obje ...

  4. Understanding the RelationshipType Enumeration [AX 2012]

    Understanding the RelationshipType Enumeration [AX 2012] 3 out of 3 rated this helpful - Rate this t ...

  5. iphone dev 入门实例3:Delete a Row from UITableView

    How To Delete a Row from UITableView I hope you have a better understanding about Model-View-Control ...

  6. The Guide To Understanding mysqlreport

    The Guide To Understanding mysqlreport This guide to understanding mysqlreport explains everything t ...

  7. 转载:10 Easy Steps to a Complete Understanding of SQL

    10 Easy Steps to a Complete Understanding of SQL 原文地址:http://tech.pro/tutorial/1555/10-easy-steps-to ...

  8. 10 Easy Steps to a Complete Understanding of SQL

    原文出处:http://tech.pro/tutorial/1555/10-easy-steps-to-a-complete-understanding-of-sql(已经失效,现在收集如下) Too ...

  9. A crawler that sent a DELETE request to every resource it encountered

    RESTful Web APIs_2013 The crawler simulates a very curious but not very picky human. Give it a URL t ...

随机推荐

  1. 控制 Android 程序使用的内存

    如何控制应用程序使用的内存? 1. 记得关闭启动的服务 当服务中的任务完成后,要记得停止该服务.可以考虑使用 IntentService,因为 IntentService 在完成任务后会自动停止. 2 ...

  2. angular input标签只能单向传递数据的问题

    angularjs input标签只能单向传递数据的问题 <ion-view title = "{{roomName}}" style = "height:90%; ...

  3. DevExpress控件的GridControl控件小结

    DevExpress控件的GridControl控件小结 (由于开始使用DevExpress控件了,所以要点滴的记录一下) 1.DevExpress控件组中的GridControl控件不能使横向滚动条 ...

  4. Map Network Driver

    K: \\10.11.80.5\deptfiling-pubgz$ O: \\10.11.80.5\deptfiling-itdgz$

  5. 用DataGridView导入TXT文件,并导出为XLS文件

    使用 DataGridView 控件,可以显示和编辑来自多种不同类型的数据源的表格数据.也可以导出.txt,.xls等格式的文件.今天我们就先介绍一下用DataGridView把导入txt文件,导出x ...

  6. ORA-01861: 文字与格式字符串不匹配

    问题:插入数据不成功 解决:借口实现类里面的sql语句带值放到数据库中运行,如果不成功是sql语句的错误.

  7. Tomcat启动失败Unrecognized Windows Sockets error: 0: JVM_Bind

    问题:Tomcat一直无法运行,或者是运行了报上面图片的哪些错误. 解决:关闭myeclipse,打开任务管理器(Ctrl+Alt+Delete)关闭javaw.exe这个进程,另外说一下,Tomca ...

  8. Python黑帽编程2.2 数值类型

    Python黑帽编程2.2  数值类型 数值类型,说白了就是处理各种各样的数字,Python中的数值类型包括整型.长整型.布尔.双精度浮点.十进制浮点和复数,这些类型在很多方面与传统的C类型有很大的区 ...

  9. 先有 Mac 还是先有银元?

    自从开设了这个公众号以后,收到最多的问题是:听了 Mac 君的介绍,我也觉得 Mac 很好,可是穷屌丝一枚,真买不起,怎么破?前几天我在微博上说,读了我的书,就有 Mac 了.居然有读者来问:这是真的 ...

  10. 用css画出三角形

    看到有面试题里会有问到如何用css画出三角形 众所周知好多图形都可以拆分成三角形,所以说会了画三角形就可以画出很多有意思的形状 画出三角形的原理是调整border(边框)的四个方向的宽度,线条样式以及 ...