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

删除Javascript Object中间的key(5)

时间:2014-11-22 15:00来源:网络整理 作者:网络 点击:
分享到:
Safari 2.x 和 3.0.4在删除函数参数时有问题; 这些属性看起来是不带DontDelete被创建的, 所以可以删除它们. Safari 2.x有更多的问题——删除非引用类型变量(如

Safari 2.x 和 3.0.4在删除函数参数时有问题; 这些属性看起来是不带DontDelete被创建的, 所以可以删除它们. Safari 2.x有更多的问题——删除非引用类型变量(如: delete 1)会抛出异常; 函数声明会创建可删除的属性(但是, 奇怪的是, 变量声明却不会); eval中的变量声明会变成不可删除的(但是函数声明是可删除的).

跟Safari类似, Konqueror(3.5, 不是4.3)会在删除非引用类型时抛出异常(如: delete 1), 并且错误地让函数变量变为可删除的.

译者注:

我测试了最新版本的chrome和firefox以及IE, 基本还是保留在除23,24会fail其它均pass的情况. 同时测试了UC和一些手机浏览器, 除了诺基亚E72的自带浏览器还会Fail 15,16之外, 其余的自带浏览器大都与桌面浏览器效果一样. 但值得一提的是, Blackberry Curve 8310/8900的自带浏览器可以pass测试23, 令我很惊讶.

Gecko DontDelete bug:

Gecko 1.8.x 浏览器 —— Firefox 2.x, Camino 1.x, Seamonkey 1.x等等. —— 表现出了一个非常有趣的bug, 对属性的显式赋值会删除它的DontDelete特性, 即使这个属性是通过变量声明或函数声明创造的.

复制代码 代码如下:

function foo(){}
delete foo; // false (as expected)
typeof foo; // "function" (as expected)
/* now assign to a property explicitly */
this.foo = 1; // erroneously clears DontDelete attribute
delete foo; // true
typeof foo; // "undefined"
/* note that this doesn't happen when assigning property implicitly */
function bar(){}
bar = 1;
delete bar; // false
typeof bar; // "number" (although assignment replaced property)

令人吃惊的是, Internet Explorer 5.5 - 8 通过了完整的测试集, 除了删除非引用类型(如: delete 1)会抛出异常(就像旧的Safari一样). 但是在IE下有更严重的bugs, 它不是那么明显. 这些bugs跟Global object有关.

IE bugs:

这整章都在说Internet Explorer的bugs? 哇! 真是令人吃惊!

在IE中(至少是IE 6-8), 以下表达式会抛出异常(当在全局代码中执行时):

this.x = 1;
delete x; // TypeError: Object doesn't support this action
这一个也会, 但是会抛出不同的异常, 这使得事情更有趣了:

var x = 1;
delete this.x; // TypeError: Cannot delete 'this.x'
这看上去好像是在IE中, 全局代码中的变量声明没有在全局对象上创建属性. 通过赋值来创建属性(this.x = 1)和之后通过delete x来删除它会抛出错误. 通过声明来创建属性(var x = 1)并且在之后通过delete this.x来删除它会抛出另一个错误.

但这还不是全部. 通过显式赋值来创建属性事实上总会引起在删除时的抛出异常. 这里不止有错误, 而且所创建的属性似乎会拥有DontDelete特性, 而这当然是不应该具有的.

this.x = 1;

delete this.x; // TypeError: Object doesn't support this action
typeof x; // "number" (still exists, wasn't deleted as it should have been!)

delete x; // TypeError: Object doesn't support this action
typeof x; // "number" (wasn't deleted again)
现在, 我们会认为 在IE下, 未声明的赋值(应当在全局对象上创建属性)确实会创建可删除的属性.

x = 1;
delete x; // true
typeof x; // "undefined"
但是, 如果你是同通过全局代码中的this引用来删除这个属性的话(delete this.x), 就会弹出一个类似的错误.

x = 1;
delete this.x; // TypeError: Cannot delete 'this.x'
如果我们想要归纳一下这种行为的话, 看起来是从全局代码中使用delete this.x来删除变量从来不可能成功. 当问题中的属性通过显式的赋值(this.x = 1)来创建时,delete抛出了一个错误; 当属性是通过未声明的赋值(x = 1)或通过声明(var x = 1)来创建时, delete抛出另外一个错误.

delete x, 另一方面来说, 应当只在属性是通过显式赋值来创建时抛出错误 ——this.x = 1.如果一个属性是通过声明来创建的(var x = 1), 删除操作从来不会发生, 并且删除操作会正确地返回false. 如果一个属性是通过未声明的赋值来创建的(x = 1), 删除操作会像期望地一样工作.

我这9月份又思考了一下这个问题, Garrett Smith建议说在IE下,

"全局变量对象(The global variable object)是实现为一个JScript对象的, 并且全局对象是由host来实现的".

Garrett使用了Eric Lippert's blog entry作为参考.

我们多多少少可以通过实施一些测试来确认这个理论. 注意到this和window看起来是应当指向同一个对象的(如果我们能够信任===操作符的话), 但是变量对象(函数声明所在的那个对象)却与this所指向的不同.

精彩图集

赞助商链接