简述

我们都知道无法通过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. *HDU 1392 计算几何

    Surround the Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  2. php下载中文名文件

    $path = APPPATH . '../htdocs/download/corp/商标申请委托书模版.doc';$filename = '商标申请委托书模版.doc';header("C ...

  3. ASP.NET中基本语言特性

    自动属性 public string Name { get; set; } 对象与集合的初始化 //自动推断类型//集合的初始化 var Products=new List<Product> ...

  4. checkbox选中状态不被改变

    让它的状态只能看不能改变,加上onclick="return false;". 也可以disabled="true";但是这个颜色变淡了; <input ...

  5. 一个基于jQuery的移动端条件选择查询插件(原创)

    下载插件 目前给出的下载是混淆了后的代码 愿意一起探讨的可以找我要源码 使用方式: var ConditionsChoose = $("#Screening").Condition ...

  6. MVC学习一:EF

    目录 一.EF修改和删除的多种方法 二.标准查询where 三.include 四.skip take 五.反射获取实例属性 六.EF DLL数据访问帮助类 一.EF修改和删除的多种方法 方法1:官方 ...

  7. .NET Core中合并Expression<Func<T,bool>>的正确姿势

    这是在昨天的 .NET Core 迁移中遇到的问题,之前在 .NET Framework 中是这样合并 Expression<Func<T,bool>> 的: public s ...

  8. UI控件(UISlider)

    @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UISlider* slider = [[UISli ...

  9. Lesson 1 A private conversation

    Text Last week I went to the theatre. I had a very good seat. The play was very intersting. I did no ...

  10. 开始研究web,mark一下

    之前想要搞引擎,经过思考之后,定位为webgl方面的引擎,这个决定早就做了,只是没有写下来   做了一些调研之后,确定使用babylon.js 和typescript 和c# 来开发   Babylo ...