Understanding delete
简述
我们都知道无法通过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的更多相关文章
- 深入理解JS的delete
		原文链接: Understanding delete原文作者: Kangax原文日期: 2010年01月10日 翻译日期: 2014年02月07日 翻译人员: 铁锚 !!!!!!!!草稿版本的翻译完成 ... 
- 深入理解Delete(JavaScript)
		深入理解Delete(JavaScript) Delete 众所周知是删除对象中的属性. 但如果不深入了解delete的真正使用在项目中会出现非常严重的问题 (: Following 是翻译 ka ... 
- javascript ES5 Object对象
		原文:http://javascript.ruanyifeng.com/stdlib/object.html 目录 概述 Object对象的方法 Object() Object.keys(),Obje ... 
- Understanding the RelationshipType Enumeration [AX 2012]
		Understanding the RelationshipType Enumeration [AX 2012] 3 out of 3 rated this helpful - Rate this t ... 
- 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 ... 
- The Guide To Understanding mysqlreport
		The Guide To Understanding mysqlreport This guide to understanding mysqlreport explains everything t ... 
- 转载: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 ... 
- 10 Easy Steps to a Complete Understanding of SQL
		原文出处:http://tech.pro/tutorial/1555/10-easy-steps-to-a-complete-understanding-of-sql(已经失效,现在收集如下) Too ... 
- 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 ... 
随机推荐
- Java 用程序给出随便大小的10 个数,序号为1-10,按从小到大顺序输出,并输出相应的序号?
			import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.uti ... 
- iOS 琐碎点------切某个或某几个角的圆角
			不说废话----------> 1.如果是切四个角的圆角,代码示例: self.picImage.layer.cornerRadius = 8; self.picImage.layer.mask ... 
- C#中常用的读取xml的几种方法(转)
			本文完全来源于http://blog.csdn.net/tiemufeng1122/article/details/6723764,仅作个人学习之用. XML文件是一种常用的文件格式,例如WinFor ... 
- Red Hat5下源码安装mysql5.6过程记录
			1.安装cmake包 [root@edu soft]# tar -xzf cmake-.tar.Z [root@edu soft]# cd cmake- [root@edu cmake-]# ./co ... 
- js_截取Url值
			"total" -->传递参数时的名字 var reg = new RegExp("(^|&)" + "total" + &q ... 
- 实例讲解 SQL 注入攻击
			这是一篇讲解SQL注入的实例文章,一步一步跟着作者脚步探索如何注入成功,展现了一次完整的渗透流程,值得一读.翻译水平有限,见谅! 一位客户让我们针对只有他们企业员工和顾客能使用的企业内网进行渗透测试. ... 
- VB.net 2010下关联与程序图标设置
			'*************************************************************************'**模 块 名:VB.net 2010下关联与程序 ... 
- ABP理论学习之数据传输对象(DTO)
			返回总目录 本篇目录 为何需要DTO 领域层抽象 数据隐藏 序列化和懒加载问题 DTO惯例和验证 DTO和实体的自动映射 使用特性和扩展方法进行映射 帮助接口 DTO用于应用层和 展现层间的数据传输. ... 
- 实现Div拖拽
			直观的理解div拖拽:当鼠标对着可拖拽部分按住后并拖动,div会跟着鼠标一起运动,并且其运动空间限制在浏览器内部,当放开鼠标时,则div停止运动. 实现div拖拽需要三个重要的事件: (1)onmou ... 
- Javascript本质第二篇:执行上下文
			在上一篇文章<Javascript本质第一篇:核心概念>中,对Javascript执行上下文做了解释,但是这些都是基于Javascript标准中对执行上下文的定义,也就是说理论上的东西,本 ... 
