龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > Javascript编程 >

删除Javascript Object中间的key(4)

时间:2014-11-22 15:00来源:网络整理 作者:网络 点击:
分享到:
复制代码 代码如下: /* `foo` is created as a property with DontDelete */ function foo(){} /* Later assignments do not modify attributes. DontDelete is still there! */ foo = 1; delete foo; // fa

复制代码 代码如下:

/* `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"

Firebug的困惑:

在Firebug中发生了什么? 为什么在console中声明的变量可以被删除, 这不是违背了我们之前所学到的知识么? 嗯, 就像我之前所说的那样, Eval代码在面对变量声明时会有特殊的表现. 在Eval中声明的变量实际上是作为不带DontDelete特性的属性被创建的.

复制代码 代码如下:

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

同样, 类似的, 当在函数代码中调用时:

复制代码 代码如下:

(function(){

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

})();

这就是Firebug反常行为的依据. 在console中的所有文本都会被当做Eval代码来解析和执行, 而不是全局或函数代码. 显然, 这里声明的所有变量最后都会成为不带DontDelete特性的属性, 所以它们都能被轻松删除. 我们需要了解这个在全局代码和Firebug控制台之间的差异.

通过Eval来删除变量:

这个有趣的eval行为, 再加上ECMAScript的另一个方面, 可以在技术上允许我们删除"non-deletable"的属性. 有关函数声明的一点是, 它们能够覆盖相同执行上下文中同名的变量.

复制代码 代码如下:

function x(){ }
var x;
typeof x; // "function"

注意函数声明是如何获得优先权并且覆盖同名变量(或者, 换句话说, 在变量对象中的相同属性)的. 这是因为函数声明是在变量声明之后被实例化的, 并且被允许覆盖它们(变量声明). 函数声明不仅会替换掉一个属性的值, 它还会替换掉那个属性的特性. 如果我们通过eval来声明一个函数, 那个函数就应该会用它自己的特性来替换掉原有的(被替换的)属性的特性. 并且, 由于通过eval声明的变量会创建不带DontDelete特性的属性, 实例化这个新函数将会实际上从属性中删除已存在的DontDelete特性, 从而使得一个属性能够被删除(并且, 显然会将其值指向新创建的函数).

复制代码 代码如下:

var x = 1;
/* Can't delete, `x` has DontDelete */
delete x; // false
typeof x; // "number"
eval('function x(){}');
/* `x` property now references function, and should have no DontDelete */
typeof x; // "function"
delete x; // should be `true`
typeof x; // should be "undefined"

不幸的是, 这种"欺骗"在目前的任何实现中都不起作用. 也许我在这漏掉了什么, 或者是这种行为只是太晦涩了以至于实现者都没有注意到它.

浏览器兼容性:

在理论上了解事物是如何工作的是有用的, 但是实践却是最重要的. 当面对变量/属性的创建/删除时, 浏览器有遵循标准么? 答案是: 在大多数情况下, 是的.

我写了一个简单的测试集来测试浏览器对于delete操作符的兼容性, 包括在全局代码, 函数代码和Eval代码下的测试. 测试集检查了delete操作符的返回值和属性值是否(像它们应当表现的一样)真的被删除了. delete的返回值并不像它的真实结果一样重要. 如果delete返回true而不是false, 这其实并不重要, 重要的是那些拥有DontDelete特性的属性没有被删除,反之亦然.

现代浏览器大致上来说是相当兼容的. 除去了我之前提到的eval特点, 如下的浏览器通过了全部的测试集: Opera 7.54+, Firefox 1.0+, Safari 3.1.2+, Chrome 4+.

精彩图集

赞助商链接