成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

firefox下delete有bug?

馬龍駒 / 1125人閱讀

摘要:看書時(shí),發(fā)現(xiàn)下的控制臺(tái)或者里,表現(xiàn)跟理論上不太一樣,表現(xiàn)則很正常,難道有問題搜了篇文章,看完才知道問題出在哪里,分享一下。

看書時(shí),發(fā)現(xiàn)firefox 35.0下的控制臺(tái)或者firebug里,delete表現(xiàn)跟理論上不太一樣,chrome表現(xiàn)則很正常,難道firefox有問題?

搜了篇文章,看完才知道問題出在哪里,分享一下。Understanding delete

Theory

那么, 為什么我們能夠刪除對(duì)象的屬性:

var o = { x: 1 };
delete o.x; // true
o.x; // undefined

卻不能刪除這樣聲明的對(duì)象:

var x = 1;
delete x; // false
x; // 1

或者函數(shù)呢:

function x(){}
delete x; // false
typeof x; // "function"

注意: 當(dāng)一個(gè)屬性無法被刪除時(shí),delete操作符只會(huì)返回false

要理解這個(gè), 我們首先需要掌握這些有關(guān)變量實(shí)例和屬性特性的概念——這些概念很不幸地, 很少在JavaScript書中被提及. 我將試著在接下來的幾個(gè)段落中簡單地復(fù)習(xí)一下這些概念. 這些概念是很難理解的!如果你不在乎"為什么這些東西會(huì)以這種方式工作"的話,盡情跳過這一章節(jié)好了.
代碼的類型:

在ECMAScript中, 有3種不同類型的可執(zhí)行代碼: 全局代碼(Global code), 函數(shù)代碼(Function code)和 Eval代碼(Eval code). 這些類型從名稱上來說或多或少是有自解釋性的, 這里有一個(gè)簡短的概述:

當(dāng)一段源代碼被看成程序(Program)時(shí), 它將會(huì)在全局環(huán)境下被執(zhí)行, 并且被認(rèn)為是全局代碼(Global code). 在一個(gè)瀏覽器環(huán)境中, 腳本元素的內(nèi)容通常被解釋為程序, 因此被作為全局代碼來執(zhí)行.

任何直接在一個(gè)函數(shù)中執(zhí)行的代碼顯然被認(rèn)為是函數(shù)代碼(Function code). 在瀏覽器中, 事件屬性的內(nèi)容(如 

)通常被解釋成函數(shù)代碼. 最后, 被應(yīng)用到內(nèi)置函數(shù)eval的代碼文本被解釋成Eval代碼(Eval code). 很快我們會(huì)發(fā)現(xiàn)為什么這種類型是特殊的.

執(zhí)行上下文(Execution context):

當(dāng)ECMAScript代碼執(zhí)行時(shí), 它通常會(huì)發(fā)生在特定的執(zhí)行上下文中.執(zhí)行上下文是一個(gè)有些抽象的實(shí)體概念, 它能幫助理解范圍(Scope)和變量實(shí)例(Variable instantiation)是如何工作的. 對(duì)三種可執(zhí)行代碼的每一種, 都有一個(gè)執(zhí)行上下文相對(duì)應(yīng). 當(dāng)一個(gè)函數(shù)被執(zhí)行的時(shí)候, 我們說"程序控制進(jìn)入了函數(shù)代碼的執(zhí)行上下文"; 當(dāng)一段全局代碼被執(zhí)行時(shí), 程序控制進(jìn)入了全局代碼的執(zhí)行上下文, 等等.

正如你所見, 執(zhí)行上下文可以在邏輯上構(gòu)成一個(gè)堆棧. 首先, 可能有一段全局代碼和其自己的執(zhí)行上下文, 然后這段代碼可能會(huì)調(diào)用一個(gè)函數(shù), 并帶著它(函數(shù))的執(zhí)行上下文. 這段函數(shù)可以調(diào)用另外一個(gè)函數(shù), 等等等等. 即使函數(shù)是遞歸調(diào)用的, 每次調(diào)用時(shí)被也會(huì)進(jìn)入一個(gè)新的執(zhí)行上下文.
活動(dòng)對(duì)象(Activation object) / 變量對(duì)象(Variable Object):

每一個(gè)執(zhí)行上下文都有一個(gè)跟其所關(guān)聯(lián)的所謂變量對(duì)象(Variable Object). 類似于執(zhí)行上下文, 變量對(duì)象是一個(gè)抽象實(shí)體, 一種用來描述變量實(shí)例的機(jī)制. 有趣之處在于, 在源代碼中聲明的變量和函數(shù)通常會(huì)被當(dāng)做屬性(properties)增加到這個(gè)變量對(duì)象上.

當(dāng)程序控制進(jìn)入全局代碼的執(zhí)行上下文時(shí), 一個(gè)全局對(duì)象(Global object)被用來作為一個(gè)變量對(duì)象. 這正是為什么聲明為全局的函數(shù)變量會(huì)變成全局對(duì)象屬性的原因.

/* remember that `this` refers to global object when in global scope */
var GLOBAL_OBJECT = this;

var foo = 1;
GLOBAL_OBJECT.foo; // 1
foo === GLOBAL_OBJECT.foo; // true

function bar(){}
typeof GLOBAL_OBJECT.bar; // "function"
GLOBAL_OBJECT.bar === bar; // true

好, 所以全局變量會(huì)變成全局對(duì)象的屬性, 但是局部變量(那些在函數(shù)代碼中定義的變量)會(huì)發(fā)生什么呢? 其實(shí)它們的行為也非常類似: 它們會(huì)變成變量對(duì)象(Variable object)的屬性. 唯一的不同在于, 當(dāng)在函數(shù)代碼中時(shí), 一個(gè)變量對(duì)象并不是全局對(duì)象, 而是所謂的活動(dòng)對(duì)象(Activation object). 活動(dòng)對(duì)象在會(huì)每次進(jìn)入函數(shù)代碼的執(zhí)行上下文時(shí)被創(chuàng)建.

并不是只有在函數(shù)代碼中聲明的變量和函數(shù)會(huì)變成活動(dòng)對(duì)象的屬性; 這也會(huì)在每個(gè)函數(shù)參數(shù)(對(duì)應(yīng)相應(yīng)的形式參數(shù)的名稱)和一個(gè)特殊的Arguments對(duì)象(以arguments為名稱)上發(fā)生. 注意, 活動(dòng)對(duì)象是一個(gè)內(nèi)部描述機(jī)制, 在程序代碼中并不能被訪問.

(function(foo){

  var bar = 2;
  function baz(){}

  /*
  In abstract terms,

  Special `arguments` object becomes a property of containing function"s Activation object:
    ACTIVATION_OBJECT.arguments; // Arguments object

  ...as well as argument `foo`:
    ACTIVATION_OBJECT.foo; // 1

  ...as well as variable `bar`:
    ACTIVATION_OBJECT.bar; // 2

  ...as well as function declared locally:
    typeof ACTIVATION_OBJECT.baz; // "function"
  */

})(1);

最后, 在Eval代碼中聲明的變量會(huì)成為調(diào)用者上下文(calling context)的變量對(duì)象的屬性. Eval代碼只是簡單地使用調(diào)用它的代碼的執(zhí)行上下文的變量對(duì)象.

var GLOBAL_OBJECT = this;

/* `foo` is created as a property of calling context Variable object,
  which in this case is a Global object */

eval("var foo = 1;");
GLOBAL_OBJECT.foo; // 1

(function(){

  /* `bar` is created as a property of calling context Variable object,
  which in this case is an Activation object of containing function */

  eval("var bar = 1;");

  /*
  In abstract terms,
  ACTIVATION_OBJECT.bar; // 1
  */

})();
屬性的特性(property attributes)

我們幾乎是已經(jīng)在這了. 既然我們已經(jīng)很清楚在變量上發(fā)生了什么(它們變成了屬性), 唯一剩下的需要理解的概念就是屬性的特性(property attributes)了. 每一個(gè)屬性可以擁有0個(gè)或多個(gè)特性, 它們從以下集合中選取: ReadOnly, DontEnum, DontDelete和 Internal. 你可以把它們認(rèn)為是flags —— 一種特性可以在屬性中存在, 也可以不存在. 對(duì)于我們今天的討論來說, 我們只對(duì)DontDelete感興趣.

當(dāng)被聲明的變量和函數(shù)成為變量對(duì)象(或者函數(shù)代碼的活動(dòng)對(duì)象, 或全局代碼的全局對(duì)象)的屬性時(shí), 這些屬性在創(chuàng)建時(shí)就帶上了DontDelete的特性. 然而, 任何顯式(或隱式)的屬性賦值所建立的屬性將不會(huì)被帶上DontDelete特性. 這就是為什么我們能夠刪除一些屬性, 但刪除不了其它的.

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"
內(nèi)置對(duì)象和DontDelete

所以, 這就是有關(guān)它(DontDelete)的所有: 屬性的一個(gè)特殊特性, 用來控制這個(gè)屬性是否能夠被刪除. 注意, 有些內(nèi)置對(duì)象的屬性是指定含有DontDelete的, 所以無法被刪除. 如特殊的arguments變量(或者, 正如我們現(xiàn)在所知道的, 一個(gè)活動(dòng)對(duì)象的屬性)擁有DontDelete. 函數(shù)實(shí)例的length屬性也具有DontDelete屬性.

(function(){

  /* can"t delete `arguments`, since it has DontDelete */

  delete arguments; // false
  typeof arguments; // "object"

  /* can"t delete function"s `length`; it also has DontDelete */

  function f(){}
  delete f.length; // false
  typeof f.length; // "number"

})();

函數(shù)參數(shù)所對(duì)應(yīng)的屬性也是從建立開始就擁有DontDelete特性的, 所以我們也無法刪除它.

(function(foo, bar){

  delete foo; // false
  foo; // 1

  delete bar; // false
  bar; // "blah"

})(1, "blah");
未聲明的賦值:

你可能還記著, 未聲明的賦值會(huì)在全局對(duì)象上建立一個(gè)屬性, 除非這個(gè)屬性已經(jīng)在這個(gè)作用域鏈中全局對(duì)象之前的其它地方被找到. 并且, 現(xiàn)在我們知道屬性賦值和變量聲明的不同之處——后者會(huì)設(shè)置DontDelete屬性, 但前者不會(huì). 我們必須清楚, 為什么未聲明的賦值會(huì)建立一個(gè)可刪除的屬性.

var GLOBAL_OBJECT = this;

/* create global property via variable declaration; property has DontDelete */
var foo = 1;

/* create global property via undeclared assignment; property has no DontDelete */
bar = 2;

delete foo; // false
typeof foo; // "number"

delete bar; // true
typeof bar; // "undefined"

請(qǐng)注意: 特性是在屬性被創(chuàng)建時(shí)被決定的, 之后的賦值不會(huì)修改已存在屬性的特性. 理解這一點(diǎn)區(qū)別非常重要.

/* `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中發(fā)生了什么? 為什么在console中聲明的變量可以被刪除, 這不是違背了我們之前所學(xué)到的知識(shí)么? 嗯, 就像我之前所說的那樣, Eval代碼在面對(duì)變量聲明時(shí)會(huì)有特殊的表現(xiàn). 在Eval中聲明的變量實(shí)際上是作為不帶DontDelete特性的屬性被創(chuàng)建的.

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

同樣, 類似的, 當(dāng)在函數(shù)代碼中調(diào)用時(shí):

(function(){

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

})();

這就是Firebug反常行為的依據(jù). 在console中的所有文本都會(huì)被當(dāng)做Eval代碼來解析和執(zhí)行, 而不是全局或函數(shù)代碼. 顯然, 這里聲明的所有變量最后都會(huì)成為不帶DontDelete特性的屬性, 所以它們都能被輕松刪除. 我們需要了解這個(gè)在全局代碼和Firebug控制臺(tái)之間的差異.
通過Eval來刪除變量:

這個(gè)有趣的eval行為, 再加上ECMAScript的另一個(gè)方面, 可以在技術(shù)上允許我們刪除"non-deletable"的屬性. 有關(guān)函數(shù)聲明的一點(diǎn)是, 它們能夠覆蓋相同執(zhí)行上下文中同名的變量.

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

注意函數(shù)聲明是如何獲得優(yōu)先權(quán)并且覆蓋同名變量(或者, 換句話說, 在變量對(duì)象中的相同屬性)的. 這是因?yàn)楹瘮?shù)聲明是在變量聲明之后被實(shí)例化的, 并且被允許覆蓋它們(變量聲明). 函數(shù)聲明不僅會(huì)替換掉一個(gè)屬性的值, 它還會(huì)替換掉那個(gè)屬性的特性. 如果我們通過eval來聲明一個(gè)函數(shù), 那個(gè)函數(shù)就應(yīng)該會(huì)用它自己的特性來替換掉原有的(被替換的)屬性的特性. 并且, 由于通過eval聲明的變量會(huì)創(chuàng)建不帶DontDelete特性的屬性, 實(shí)例化這個(gè)新函數(shù)將會(huì)實(shí)際上從屬性中刪除已存在的DontDelete特性, 從而使得一個(gè)屬性能夠被刪除(并且, 顯然會(huì)將其值指向新創(chuàng)建的函數(shù)).

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"

不幸的是, 這種"欺騙"在目前的任何實(shí)現(xiàn)中都不起作用. 也許我在這漏掉了什么, 或者是這種行為只是太晦澀了以至于實(shí)現(xiàn)者都沒有注意到它.

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/91451.html

相關(guān)文章

  • FireFoxCanvas使用圖像合成繪制SVG的Bug

    摘要:本文適合適合對(duì)繪制圖形學(xué)前端可視化感興趣的讀者閱讀。結(jié)論已經(jīng)明顯瀏覽器下,用下繪制繪制圖的時(shí)候,的設(shè)置將不生效。下面是一段用于測(cè)試的代碼,表示用源圖像的形狀去挖空目標(biāo)圖像。后續(xù)繪制用臨時(shí)的替代圖片。 本文適合適合對(duì)canvas繪制、圖形學(xué)、前端可視化感興趣的讀者閱讀。 楔子 所有的事情都會(huì)有一個(gè)起因。最近產(chǎn)品上需要做一個(gè)這樣的功能:給一些圖形進(jìn)行染色處理。想想這還不是順手拈來的事情,早...

    mudiyouyou 評(píng)論0 收藏0
  • 瀏覽器兼容你知多少?

    摘要:在各大瀏覽器廠商的發(fā)展過程中,它們對(duì)的標(biāo)準(zhǔn)各有不同的實(shí)現(xiàn),標(biāo)準(zhǔn)不同存在差異所以產(chǎn)生兼容性的問題。它是一種對(duì)特定的瀏覽器或?yàn)g覽器組顯示或隱藏規(guī)則或聲明的方法。但是及更低版本瀏覽器會(huì)繼續(xù)解析。 為什么會(huì)存在瀏覽器兼容問題? 首先要了解兼容,我們先得了解一下為什么會(huì)存在瀏覽器兼容問題。在各大瀏覽器廠商的發(fā)展過程中,它們對(duì)web的標(biāo)準(zhǔn)各有不同的實(shí)現(xiàn),標(biāo)準(zhǔn)不同存在差異所以產(chǎn)生兼容性的問題。 瀏覽...

    txgcwm 評(píng)論0 收藏0
  • 【踩坑】近來在Firefox上遇到的一些坑

    摘要:最近在幫人解決下的一些兼容問題。驗(yàn)證不通過的話,輸入框會(huì)加上紅色的邊框。然后妹紙?jiān)诿枋鲋姓f的是瀏覽器中,修改密碼頁面,輸入框中不輸入任何字符,輸入框顏色也是紅的我還以為又是哪里的寫得不對(duì)呢。最后發(fā)現(xiàn),輸入框好像都帶了個(gè)屬性。 因?yàn)楣ぷ饕荒甓嘁詠恚龅墓ぷ骰径际呛蛍ebkit系列打交道。 先是做m站,后來做了兩個(gè)app內(nèi)嵌的hybrid項(xiàng)目,從來只考慮webkit前綴和相關(guān)的偽類。 最...

    JaysonWang 評(píng)論0 收藏0
  • 【踩坑】近來在Firefox上遇到的一些坑

    摘要:最近在幫人解決下的一些兼容問題。驗(yàn)證不通過的話,輸入框會(huì)加上紅色的邊框。然后妹紙?jiān)诿枋鲋姓f的是瀏覽器中,修改密碼頁面,輸入框中不輸入任何字符,輸入框顏色也是紅的我還以為又是哪里的寫得不對(duì)呢。最后發(fā)現(xiàn),輸入框好像都帶了個(gè)屬性。 因?yàn)楣ぷ饕荒甓嘁詠?,做的工作基本都是和webkit系列打交道。 先是做m站,后來做了兩個(gè)app內(nèi)嵌的hybrid項(xiàng)目,從來只考慮webkit前綴和相關(guān)的偽類。 最...

    AJie 評(píng)論0 收藏0
  • 如何禁止JavaScript對(duì)象重寫?

    摘要:譯者按使用和,可以禁止重寫對(duì)象。引入了一些方法,允許開發(fā)者限制對(duì)象重寫。不要重寫他人的對(duì)象不要重寫他人的對(duì)象,這是的黃金法則。如果你修改的是對(duì)象比如,這會(huì)導(dǎo)致非常嚴(yán)重的后果。 譯者按: 使用Object.preventExtensions()、Object.seal()和Object.freeze(),可以禁止重寫JavaScript對(duì)象。 譯者:Fundebug 原文:Preve...

    jubincn 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<