删除window.alert返回true, 即使这个属性完全没有任何应该导致这样的结果的理由. 它将解析为一个引用(所以不会在第一步就返回true). 这是个window对象的直接属性(所以不会在第二步返回true). 所以delete唯一能够返回true的情况就是到达第四步并且真正删除那个属性. 然而, 这个属性从未被删除.
这个故事的寓意是: 永远不要相信宿主对象.
ES5 严格模式:
所以, 严格模式的ECMAScript5给我们带来了什么呢? 它介绍了很少的一些限制. 当delete操作符的表达式是一个变量的直接引用, 函数参数或者函数标示符时, 语法错误将会被抛出. 另外, 如果属性具有内部特性[[Configurable]] == false, 则一个类型错误将会被抛出.
复制代码 代码如下:
(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
})();
另外, 删除未声明的变量(或者说未解析的引用)将也会抛出语法错误:
"use strict";
delete i_dont_exist; // SyntaxError
未声明的赋值跟严格模式下未声明的变量所表现的行为类似(除了这次是引发引用错误而不是语法错误):
"use strict";
i_dont_exist = 1; // ReferenceError
正如你现在所明白的, 所有的限制多多少少是有道理的, 因为删除变量, 函数声明和 参数会导致这么多混乱. 与其静默地忽略删除操作, 严格模式采用了一种更加激进和更具描述性的措施.
总结:
这篇博文最后变得相当的长, 所以我不准备再去谈论类似于用delete删除数组对象或它的含义是什么等. 你可以参考MDC文章对其专门的解释(或者阅读标准和自己做实验).
这里有一份对于JavaScript中删除操作是如何工作的简短的总结:
变量和函数声明是活动对象或者全局对象的属性
属性拥有一些特性, 这其中的DontDelete是决定这个属性能否被删除的那个特性.
在全局或者函数代码中的变量和函数声明总是创建带有DontDelete特性的属性.
函数参数总是活动对象的属性, 并且带有DontDelete.
在Eval代码中声明的变量和函数总是创建不带DontDelete的属性.
新的属性在建立时是没有特性的(当然也没有DontDelete).
宿主对象被允许自己决定如何对delete操作做出反应.
如果你想要对这里所描述的东西更加熟悉的话, 请参阅 ECMA-262 3rd edition specification.
我希望你能够享受这篇文章, 并且学到一些新的东西. 欢迎提出任何问题, 建议或者纠正.
您可能感兴趣的文章: