不会的。回家去种植你的土地。

复制代码代码如下所示:

删除thisisobject {key}

或

删除thisisobject.key



顺便说一下,让我们来谈谈删除的用法。

几周前,我有机会读斯托扬斯特凡诺夫面向对象的Javascript的书。这本书对亚马逊(12篇评论,5颗星)有很高的评价,所以我很想看看它不是一本值得推荐的书,所以我开始阅读章节功能。我很欣赏这本书来解释事情。例子是在一个非常漂亮的,渐进的方法来组织,看起来甚至初学者可以很容易掌握知识。然而,几乎立刻,我发现了一个有趣的误解,除了一些其他错误(例如不同的函数声明和函数表达式),但我们现在不讨论这些问题。

这本书声称:

函数被视为一般变量——它可以被复制到不同的变量,甚至被删除。在这个解释之后,添加了一个例子。

复制代码代码如下所示:

函数(a,b){返回a;b;}

var =总和;

删除总和

真正的

类型的总和;

未定义



忽略一些缺失的分号,可以看出有几个代码错误在哪里,很明显,删除这个变量操作的总和是不成功的。delete表达式不应该返回true,类型和不应该回到定义。所有这些,因为Javascript变量是不可能的,以这种方式声明是不可能的。

因此,在这种情况下,最终发生的是错误或特殊用法可能不是这样。这段代码实际上是在Firebug控制台的实际产出,Stoyan作为快速检测工具。它几乎和其他萤火虫符合删除规则为好。Firebug是误入歧途Stoyan!那么,这里发生了什么

在回答这个问题之前,我们首先需要了解Javascript中的删除操作符是如何工作的:什么是可以删除的,什么是不能删除的,我将尝试解释这个问题。我们将看看萤火虫是奇怪的实现,是不是很奇怪。在一份声明中,将进一步了解变量的功能,并指派它们最终删除这些场景背后隐藏的东西。我们将看看在浏览器的兼容性和一些最臭名昭著的bug。我们还将讨论ES5的严格模式,以及它如何改变行为的删除操作。

我要交换的Javascript和ECMAscript的使用,这意味着ECMAscript(除非Mozilla Javascript实现显然是谈论)

正如预期的那样,在网络中,对删除的解释相当稀少。MDC文章可能是对资源最好的理解,但不幸的是,它遗漏了这个主题的一些有趣的细节。奇怪的是,一个奇怪的原因,已经忘记了什么是MSDN参考Firebug。在这些领域几乎毫无用处。

理论

那么,为什么我们可以删除对象的属性呢:

复制代码代码如下所示:

var:x:1 };

删除OX; / /真的

OX; / /未定义



不能删除此类声明的对象:

复制代码代码如下所示:

变量x=1;

删除x; / false

x 1;



或函数:

复制代码代码如下所示:

函数(x){ }

删除x; / false

typeof X; / / 功能



注意:当属性不能被删除时,删除操作符只返回false。

为了理解这一点,我们首先需要掌握概念的相关变量和属性特征,不幸的是这些概念在本书中很少提到。我将在下面的段落中尝试简要地回顾这些概念。这些概念很难理解!如果你不关心为什么这些事情会以这种方式工作

代码类型:

在ECMAscript,有3个不同的可执行代码:国际代码,功能代码和程序代码。这些类型或多或少是自解释的名称。这里是一个简短的概述。

当一个源代码被视为一个程序(程序)时,它将在全局环境中执行,并被认为是全局代码(全局代码)。在浏览器环境中,脚本元素的内容通常被解释为程序,因此它们被作为全局代码执行。

任何直接在函数中执行的代码显然被认为是一个函数代码(函数代码)。在浏览器中,事件属性的内容通常被解释为函数代码。

最后,文中的代码已被应用于内置函数eval被解释为一个程序代码(程序代码)。很快我们就会发现为什么这种类型是特殊的。

执行上下文(执行上下文):

当ECMAscript被执行,它通常发生在特定的执行环境。执行上下文是一个抽象的实体概念,它有助于理解范围(变量实例化)的范围,实例变量是如何工作的。对于三种可执行代码,每种代码都有相应的上下文执行。当执行一个函数时,我们将执行上下文称为程序控制函数代码;当执行全局代码时,程序控制进入执行上下文、全局代码等。

如您所见,执行上下文可以在逻辑上形成堆栈。首先,可能有一个全局代码和它的执行上下文,然后这个代码可以调用一个函数,并用它(函数)执行上下文。这个函数可以调用另一个函数,所以即使函数是递归调用,每个调用都将进入一个新的执行上下文。

活动对象(激活对象)/变量对象(变量对象):

每个执行上下文都与所谓的变量对象(变量对象)相关联。类似于执行上下文变量对象是一个抽象实体,一个用来描述实例变量机制的术语。有趣的是,源代码中声明的变量和函数的数量通常被作为添加到变量对象的属性(属性)处理。

当程序控制进入全局代码的执行上下文时,全局对象(全局对象)用作变量对象。这就是为什么全局变量声明成为全局对象的属性的原因。

复制代码代码如下所示:

记住,在全局范围内,这是指全局对象。

无功global_object =这;

var = 1;

global_object.foo / / 1;

foo = global_object.foo; / /真的

函数(bar){ }

类型global_object.bar; / / 功能

global_object.bar = / /真棒;



那么,全局变量将成为全局对象属性,但是本地变量(在代码中的变量函数中定义的)会发生什么,但是它们的行为也非常相似:它们将成为对象变量(变量对象)属性。唯一的区别是,当代码的功能,一个变量对象不是一个全局对象,而是所谓的活动对象(激活对象)。在执行上下文中创建的活动对象将输入每个函数代码。

不仅变量函数和函数属性的代码中的语句将成为活动对象,它也将在每个参数(相应的对应形参)的名称和一个特殊的参数对象(参数名称)中起作用。注意,活动对象是内部描述机制,不能在程序代码中访问。

复制代码代码如下所示:

(函数)({){

var bar = 2;

功能(Baz){ }

*

用抽象的术语,

特殊'参数'对象成为包含函数的激活对象的属性:

activation_object.arguments; / /参数对象

…以及论点'富':

activation_object.foo / / 1;

…以及变量'酒吧':

activation_object.bar / / 2;

…以及本地声明的函数:

类型activation_object.baz; / / 功能

* /

})(1);



最后,声明的变量在程序代码将成为调用者的上下文的变量对象的属性(调用上下文)。eval代码只是使用可变对象,调用它的代码的执行上下文。

复制代码代码如下所示:

无功global_object =这;

创建是作为调用上下文变量对象的属性,

在本例中是全局对象。

eval('var foo = 1;);

global_object.foo / / 1;

(函数(){())

bar是作为调用上下文变量对象的属性创建的,

在本例中是包含函数的激活对象。

eval('var酒吧= 1;);

*

用抽象的术语,

activation_object.bar / / 1;

* /

});



属性(属性属性)

我们差不多已经到了。既然我们已经很清楚什么变量(它们变成了属性),只需要了解概念的特性就是属性(属性属性)。每个属性可以有0个或更多的特点,从以下选择:只读,dontenum,dontdelete和内部,你可以把它们作为存在的属性标志——一个特点,也可以不存在。我们今天的讨论,我们只对dontdelete。

变量和函数的声明的对象变量的时候(全局对象的活动对象或函数代码或全局代码)属性,这些属性在创建以dontdelete特点。然而,没有(显式或隐式)属性赋值不会随着dontdelete特点建立。这就是为什么我们可以删除一些属性,但不能删除另一个属性。

复制代码代码如下所示:

无功global_object =这;

是一个全局对象的属性。

这是通过创建变量声明等都dontdelete属性。

这就是为什么不能删除它。

var = 1;

删除

类型 / /数言;

bar是全局对象的一个属性。

它通过创建的函数声明,dontdelete属性。

这就是为什么它也不能被删除。

函数(bar){ }

删除条形图;

类型的酒吧; / / 功能

`巴兹`也是 /全局对象的属性。

然而,它是通过产权转让,所以一直没有dontdelete

这就是为什么它可以被删除。

global_object.baz = 'blah;

删除global_object.baz; / /真的

类型global_object.baz; / / 的定义



内置对象和DontDelete

所以,这是所有关于它(dontdelete):一个特殊的属性,这个属性是用来控制是否可以删除。值得注意的是,一些内置对象的属性指定与DontDelete,因此无法删除。作为一个特殊的参数变量(或者,正如我们现在所知道的,一个活动对象的属性)属性dontdelete长度。函数实例也有dontdelete财产。

复制代码代码如下所示:

(函数(){())

不能删除因为它/ `争论`,有 / dontdelete

删除参数; false

类型参数; / /对象

不能删除功能的`长度`它*还* DontDelete;

函数(f){ }

删除f.length; / /假

类型f.length / /数;

});



属性对应的功能参数也有从成立开始dontdelete特征,所以我们不能删除它。

复制代码代码如下所示:

(函数(bar,bar){)

删除

1;

删除条形图;

酒吧; / / 'blah

})(1,'blah);



未分配:

您可能会记住,赋值语句不会在全局对象中建立一个属性,除非在全局范围链对象之前找到了其他位置。现在我们知道,设置dontdelete性质差异属性赋值和变量声明--后者,但前者不是我们。必须清楚,为什么赋值语句不能建立一个删除属性。

复制代码代码如下所示:

无功global_object =这;

通过变量声明*属性创建全局属性* DontDelete;

var = 1;

通过申报财产分配*创建全局属性没有* DontDelete;

bar=2;

删除

类型 / /数言;

删除条形图;

类型 / /定义吧;



注意:特性是在创建属性时确定的,后续赋值不会修改现有属性的属性。理解这种差异是非常重要的。

复制代码代码如下所示:

` foo `创建作为一个dontdelete财产* *

函数(富){ }

以后的赋值不会修改属性。* dontdelete仍然存在!

= 1;

删除

类型 / /数言;

但是分配到一个不存在的属性,

创建属性空属性(所以没有dontdelete)。









































































` X `物业现在参考/功能,应该没有dontdelete。

typeof X; / / 功能

删除x;应该是真的

typeof X; / / 应定义



不幸的是,这种欺骗在目前的任何实施中都不是有效的。也许我错过了什么,或者这种行为是如此模糊,实施者没有注意到它。

浏览器的兼容性:

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

我写的一个简单的测试集测试与删除操作的浏览器兼容性,包括全球的代码,在测试功能的代码和程序代码。删除删除操作符和属性值(它们是否应该像真的一样)的返回值的测试集被删除。删除的重要返回值,不同于它的实际结果。如果删除返回而不是虚假的事实,这是不重要的,这个属性有dontdelete特性尚未被删除是很重要的,反之亦然。

一般来说,现代浏览器是相当兼容的。除了我前面提到的eval的特点,以下浏览器已经通过了所有的测试集:歌剧7.54 +,1 + Firefox,Safari 3.1.2铬+,4 +的..

Safari 2。在删除函数参数X问题和3.0.4;这些特性似乎没有了dontdelete,这样你可以删除它们。Safari 2。X有更多的问题:删除非引用类型的变量(如删除1)将抛出一个异常;属性函数语句将创建可以被删除(但奇怪的是,变量的声明并不);在评价变量声明将成为不可删除的(但语句的功能是删除)。

类似于Safari,Konqueror(3.5,4.3)抛出一个异常去除非引用类型时,如删除1,错误地将功能变量被删除。

译者注:

我测试了Chrome和Firefox和IE浏览器的最新版本,仍然保留在23,24通除了其他条件不。同时测试了UC和一些手机上的浏览器,除了诺基亚E72的浏览器会失败15,16,同样效果的其他浏览器和桌面浏览器。但值得一提的是,黑莓曲线8310 8900浏览器可以通过23测试,令我吃惊。

壁虎dontdelete bug:

壁虎1.8。X浏览器,Firefox 2。x,Camino 1。X,X等1个。-显示一个非常有趣的BUG,属性的显式分配将删除其dontdelete特征,即使这个属性是通过变量的声明和函数的声明。

复制代码代码如下所示:

函数(富){ }

删除;假(如预期)

类型 / / 言;功能(如预期)

现在显式地分配给一个属性。

this.foo = 1; / /错误地清除dontdelete属性

删除

类型 / /定义foo;

请注意,当*隐式分配属性时不会发生这种情况。

函数(bar){ }

酒吧= 1;

删除条形图;

类型的酒吧; / / (虽然分配取代财产)



令人惊讶的是,Internet Explorer 5.5 - 8通过一个完整的测试集,除了删除非引用类型(如删除1)外,还会抛出一个异常(如旧Safari)。但是伊江的臭虫比较严重,不那么明显。具有全局对象的bug。

IE浏览器漏洞:

这一章讲述的是Internet Explorer的bug哇!太惊人了。

在IE(至少是第6-8次)中,下面的表达式将抛出异常(在全局代码中执行):

这个,x=1;

删除X;对象不支持此行动 / /列表:

这一个会,但它会抛出一个不同的例外,这使它更有趣:

变量x=1;

删除不delete'this。X。X; / /列表:

在伊江中,代码中的全局变量声明并没有在全局对象中创建一个属性。通过指定一个值来创建属性(这个x = 1),然后通过删除x来删除它将抛出一个错误。通过语句创建属性(var x=1),并在删除后删除这个x,它会抛出另一个错误。

但这还不是全部。通过创建显式属性,属性总是会导致在删除时引发的异常。这不仅仅是错误,和属性的创建将似乎有dontdelete财产,这当然是不应该有。

这个,x=1;

删除此。X;对象不支持此行动 / /列表:

typeof X; / / (仍然存在,不删除也应该如此!)

删除X;对象不支持此行动 / /列表:

typeof X; / / (不删除了)

现在,我们认为在IE下面,未声明的赋值(应该在全局对象上创建一个属性)确实创建一个删除属性。

x=1;

删除x

类型 / /定义X;

但是,如果使用全局代码中的引用删除此属性(删除此x),就会弹出类似的错误。

x=1;

删除不delete'this。X。X; / /列表:

如果我们要总结这一行为,似乎从全局变量将不会成功在代码中使用删除。当属性的显式分配(这个x = 1)的创建,删除,抛出一个错误;当属性不能通过赋值语句(x = 1)或声明(var x = 1)的创建,删除抛出一个错误。

另一方面,删除x应该只在属性错误时--这个= x = 1。如果属性是由显式赋值创建的语句抛出(var x = 1)创建的,则删除操作从未发生,而删除操作正确返回false。如果某个属性是由赋值语句创建的(x = 1),则删除操作将按预期工作进行。

九月我又想到了这个问题,Garrett Smith建议在IE下面做这个,

全局变量对象(全局变量对象)是作为一个Jscript对象实现的,和全局对象是通过主机。

加勒特利用Eric Lippert的博客作为参考。

我们可以或多或少地通过一些测试来证实这一理论的实施。注意,这个和窗口似乎指向同一个对象(如果我们可以信任你,但=操作符)变量对象(对象函数值),这一点是不同的。

复制代码代码如下所示:

在全局代码中

功能getbase(){ return这个;}

(getbase)this.getbase(假); / / = = =

(这个。getbase)this.getbase(true); / / = = =

(窗口。getbase)this.getbase(true); / / = = =

(窗口。getbase)getbase(假); / / = = =



误解:

要理解事物为什么以这种方式工作是不可低估的。我在网上看到一些关于删除操作员的误解。例如,在这个计算器的答案(以惊人的高评级)是自信的解释。

当目标操作数不是对象属性时,删除应该是不可操作的。

现在我们对删除核心操作行为有了更好的理解,答案显然是错误的。删除不区分因变量和属性(事实上,删除了,这是一个引用类型),只有dontdelete特点照顾的事实(是否属性本身存在)。

看到各种彼此的误解,是非常有趣的,在同一主题中的第一个只删除变量(这将不会有效果,除非它是宣布在EVAL),而另一个人提供了一个纠错说明如何删除可以删除在全局变量的代码,函数中的代码不。

要更仔细地了解网络上的Javascript解释,最理想的方法是了解问题的实质。)

删除和主机对象(主机对象):

删除算法可能是这样的:

如果操作数不是引用类型,则返回true。

如果对象没有名称的直接属性,则返回到真(如我们所知,对象可以是活动的或全局的)。

如果属性存在,但有dontdelete特征,返回假

其他情况下,删除属性并返回true

但是,主机对象行为中的删除运算符很难预测。这种行为实际上并没有错:(根据标准),允许宿主对象读(内部{ } } }方法),编写({ } }方法)和删除(内部删除)}方法,几个操作符执行任何行为。这种定制{ } }格雷斯是宿主对象行为变得如此混乱。

我们已经看到一些IE的怪癖,删除特定的对象(显然是指作为宿主对象实现)会抛出一个错误。一些火狐的版本将被删除时window.location。当操作数是主机对象时,您不能信任删除的返回值。让我们看看Firefox发生了什么:

复制代码代码如下所示:

警告是一个直接的 /性能` `窗口(如果我们相信` hasownproperty `)。

window.hasownproperty('alert '); / /真的

删除window.alert; / /真的

类型 / /功能window.alert;



删除window.alert返回true,即使这个属性应该是完全没有任何结果的原因。它将解析为一个引用(因此它不是返回true的第一步)。这是窗口对象的直接属性(因此它不会在第二步返回true)。删除)只能返回true。在第四步和删除的真属性。但是,这个属性从未被删除。

这个故事的寓意是:永远不要相信主人。

ES5的严格模式:

所以,严格ecmascript5模式给我们带来它所描述的一些限制。当表达式删除运算符直接引用变量、函数参数或函数标识符时,将抛出语法错误。此外,如果该属性具有可配置} = false的内部特性,则将抛出一种错误类型。

复制代码代码如下所示:

(函数)({){

使用严格;在这个函数中启用严格的模式

VaR的酒吧;

功能(Baz){ }

删除foo; / /查询(删除时的说法)

删除吧; / /查询(当删除变量)

删除巴兹; / /查询(当删除函数声明创建的变量)

函数实例的‘长度'有:可配置}:false

删除(功能(长度){ }); / /列表

});



此外,删除未声明的变量(或未解析的引用)也将把语法错误:

使用严格;

删除i_dont_exist; / /查询

未声明赋值类似于严格模型中未声明变量的行为(除此之外,这是一个引用错误,而不是语法错误)。

使用严格;

i_dont_exist = 1; / / referenceerror

正如您现在看到的,所有的限制或多或少都是合理的,因为删除变量、函数声明和参数会造成很多混乱。严格地使用了更为激进和描述性的度量方法,而不是默默地忽略删除操作。

总结:

这个博客终于变得相当长了,所以我不想谈论删除数组对象,比如删除或者它的意义。您可以参考MDC文章的特殊解释(或阅读标准并自行完成)。

下面简要介绍了Javascript中的删除操作是如何工作的:

变量和函数声明是活动对象或全局对象的属性。

性能有一定的特点,而且在这dontdelete是特征决定这个属性可以被删除。

在全球或函数代码总是创造dontdelete特性声明的变量和函数。

函数的参数都是活动对象的属性,有dontdelete。

变量和函数的声明在eval代码始终创建一个属性没有dontdelete。

新的属性特征时不成立(当然,没有dontdelete)。

宿主对象被允许决定如何对删除操作作出响应。

如果你想与这里所描述的更熟悉,看到ECMA-262第三版规范。

我希望你能喜欢这篇文章并学习一些新的东西。欢迎任何问题、建议或更正。