<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Javascript中的delete

      一、問題的提出 

      我們先來看看下面幾段代碼,要注意的是,以下代碼不要在瀏覽器的開發者工具(如FireBug、Chrome Developer tool)中運行,原因后面會說明: 

      為什么我們可以刪除對象的屬性: 

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

      但不以刪除像這樣聲明的變量: 

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


      也不能刪除像這樣定義的函數: 

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


      注意:當delete操作符返回true時表示可以刪除,返回false表示不能刪除 

        要理解這一點,我們首先需要掌握像變量實例化和屬性特性這樣的概念--遺憾的是這些內容在一些javascript的書中很少講到。理解它們并不難,如果你不在乎它們為什么這么運行,你可以隨意的跳過這一部分。 

      二、代碼類型 

        在ECMAScript中有三種類型的可執行代碼:Global code(全局代碼)、Function code(函數代碼)和 Eval code(放在Eval中執行的代碼)。 

      var x=1;//Global code 
      function test(){ 
      var y=2;//Function Code 
      eval("var z=3");//Eval Code in Function 
      } 
      eval("function evalTest(){}");//Eval Code in Global 


      三、執行上下文 

        當ECMAScript 代碼執行時,它總是在一定的上下文中運行,執行上下文是一個有點抽象的實體,它有助于我們理解作用域和變量實例化如何工作的。對于三種類型的可執行代碼,每個都有執行的上下文。當一個函數執行時,可以說控制進入到函數代碼(Function code)的執行上下文。全局代碼執行時,進入到全局代碼(Global code)的執行上下文。 

        正如你所見,執行上下文邏輯上來自一個棧。首先可能是有自己作用域的全局代碼,代碼中可能調用一個函數,它有自己的作用域,函數可以調用另外一個函數,等等。即使函數遞歸地調用它自身,每一次調用都進入一個新的執行上下文。 

      四、Activation object(激活對象)/Variable object(變量對象) 

        每一個執行上下文在其內部都有一個Variable Object。與執行上下文類似,Variable object是一個抽象的實體,用來描述變量實例化的機制。有趣的是在代碼中聲明的變量和函數實際上被當作這個變量對象的屬性被添加。 

        當進入全局代碼的執行上下文時,一個全局對象用作變量對象。這也正是為什么在全局范圍中聲明的變量或者函數變成了全局對象的屬性。 

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

      全局變量變成了全局對象的屬性,但是,那些在函數代碼(Function code)中定義的局部變量又會如何呢?行為其實很相似:它成了變量對象的屬性。唯一的差別在于在函數代碼(Function code)中,變量對象不是全局對象,而是所謂的激活對象(Activation object)。每次函數代碼(Function code)進入執行作用域時,就會創建一個激活對象(Activation object)。 

        不僅函數代碼(Function code)中的變量和函數成為激活對象的屬性,而且函數的每一個參數(與形參相對應的名稱)和一個特定Arguments 對象也是。注意,激活對象是一種內部機制,不會被程序代碼真正訪問到。 

      (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 代碼(Eval code)中聲明的變量作為正在調用的上下文的變量對象的屬性被創建。Eval 代碼(Eval code)只使用它正在被調用的哪個執行上下文的變量對象。 

      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 
      */ 
      
      })(); 


      五、屬性特性 

        現在變量會怎樣已經很清楚(它們成為屬性),剩下唯一的需要理解的概念是屬性特性。每個屬性都有來自下列一組屬性中的零個或多個特性--ReadOnly, DontEnum, DontDelete 和Internal,你可以認為它們是一個標記,一個屬性可有可無的特性。為了今天討論的目的,我們只關心DontDelete 特性。 

        當聲明的變量和函數成為一個變量對象的屬性時--要么是激活對象(Function code),要么是全局對象(Global code),這些創建的屬性帶有DontDelete 特性。但是,任何明確的(或隱含的)創建的屬性不具有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" 


      六、內置屬性和DontDelete 

        一句話:屬性中一個獨特的特性(DontDelete)控制著這個屬性是否能被刪除。注意,對象的內置屬性(即對象的預定義屬性)有DontDelete 特性,因此不能被刪除。特定的Arguments 變量(或者,正如我們現在了解的,激活對象的屬性),任何函數實例的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" 
      
      })(); 

      與函數參數相對應的創建的屬性也有DontDelete 特性,因此也不能被刪除。 


      (function(foo, bar){ 
      
      delete foo; // false 
      foo; // 1 
      
      delete bar; // false 
      bar; // 'blah' 
      
      })(1, 'blah'); 

       

      七、未聲明的賦值 


        簡單地就是未聲明的賦值在一個全局對象上創建一個可刪除的屬性。 

      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;//可理解為 window.bar=2; 根據上面的第五點是可以刪除的 
      
      delete foo; // false 
      typeof foo; // "number" 
      
      delete bar; // true 
      typeof bar; // "undefined" 


      請注意,DontDelete特性是在屬性創建的過程中確定的,后來的賦值不會修改現有屬性已經存在的特性,理解這一點很重要。 


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

       

      八、Eval code 
        在Eval中創建的變量或方法比較特別,沒有DontDelete特性,也就是說可以刪除。 

      eval("var x = 1;"); 
      console.log(x); // 1 
      delete x; 
      console.log(typeof x); // undefined 
      
      eval("function test(){ var x=1; console.log(delete x);/* false */;return 1;}"); 
      console.log(test()); // 1 
      delete test; 
      console.log(typeof test); // undefined 

       

      注意,這里說的在Eval中創建的變量或方法不包括方法內部的變量或方法,如上面代碼中的紅色部分,仍然跟之前講的一致:不能被刪除。 

      九、FireBug的困惑 

        我們看一段在FireBug中執行的代碼結果: 

      var x=1; 
      delete x; 
      console.log(typeof x);//undefined 
      
      function y(){ 
      var z=1; 
      console.log(delete z);//false 
      } 
      y(); 
      delete y; 
      console.log(typeof y);//undefined 

       

      這明明是違反上述規則的,但跟上面第八點對比后發現,這正在代碼在eval中執行的效果。雖然沒有證實,但我猜測FireBug(Chrome Developer tool)中控制臺代碼是用eval執行的。 

      所以,當大家在測試JS代碼時,如果涉及到當前上下文環境時特別要注意。 

      十、delete操作符刪除的對象 

        C++中也有delete操作符,它刪除的是指針所指向的對象。例如: 


      class Object { 
      public: 
      Object *x; 
      } 
      
      Object o; 
      o.x = new Object(); 
      delete o.x; // 上一行new的Object對象將被釋放 

       

      但Javascript的delete與C++不同,它不會刪除o.x指向的對象,而是刪除o.x屬性本身。 

      var o = {}; 
      o.x = new Object(); 
      delete o.x; // 上一行new的Object對象依然存在 
      o.x; // undefined,o的名為x的屬性被刪除了 

       

       在實際的Javascript中,delete o.x之后,Object對象會由于失去了引用而被垃圾回收, 所以delete o.x也就“相當于”刪除了o.x所指向的對象,但這個動作并不是ECMAScript標準, 也就是說,即使某個實現完全不刪除Object對象,也不算是違反ECMAScript標準。 

        “刪除屬性而不是刪除對象”這一點,可以通過以下的代碼來確認。 

      var o = {}; 
      var a = { x: 10 }; 
      o.a = a; 
      delete o.a; // o.a屬性被刪除 
      o.a; // undefined 
      a.x; // 10, 因為{ x: 10 } 對象依然被 a 引用,所以不會被回收 


      另外,delete o.x 也可以寫作 delete o["x"],兩者效果相同。 

      十一、其他不能被刪除的屬性 

        除了上面說過的內置屬性(即預定義屬性)不能被刪除外,prototype中聲明的屬性也不能delete: 

      function C() { this.x = 42; } 
      C.prototype.x = 12; 
      C.prototype.y = 13; 
      
      var o = new C(); 
      o.x; // 42, 構造函數中定義的o.x 
      
      delete o.x; //true 刪除的是自身定義的x 
      o.x; // 12, prototype中定義的o.x,即使再次執行delete o.x也不會被刪除 
      
      delete o.y; //true,因為 o自身沒有o.y屬性,y存在于prototype鏈中,也就是說對象自身屬性和prototype屬性是不同的 
      o.y; //13 

       

      小結 


        上面說了那么多,希望對大家認識JavaScript中的Delete有所幫助。由于水平有限,不保證完全正確,如果發現錯誤歡迎指正。 

      posted @ 2015-10-19 09:13  nd  閱讀(935)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲欧美日韩在线不卡| 最近中文字幕完整版hd| 欧美熟妇性XXXX欧美熟人多毛 | 四虎女优在线视频免费看| 亚洲天堂一区二区三区三州| 国产第一页浮力影院入口| 玉龙| 视频一区二区三区四区不卡| 国产精品麻豆中文字幕| 国产精品毛片久久久久久久 | 性一交一乱一伦| 免费看视频的网站| 免费大黄网站在线观看| 99国产午夜福利在线观看| 日韩不卡在线观看视频不卡| 久国产精品韩国三级视频| 无锡市| 日本一码二码三码的区分| 国产稚嫩高中生呻吟激情在线视频| 乱码中字在线观看一二区| 泉州市| 91一区二区三区蜜桃臀| 亚洲AV永久无码天堂网一线| 人妻少妇精品视频专区| 高颜值午夜福利在线观看| 国产亚洲制服免视频| 日韩伦理片| 亚洲精品综合久久国产二区| 亚洲欧美一区二区成人片| 蜜臀av性久久久久蜜臀aⅴ麻豆 | 托克逊县| 蜜桃av亚洲精品一区二区| 成人特黄A级毛片免费视频| 无码日韩精品一区二区三区免费| 亚洲日韩AV秘 无码一区二区| 亚洲狠狠婷婷综合久久久| 真人在线射美女视频在线观看| 亚洲精品麻豆一区二区| 麻豆精品一区二区三区蜜臀 | 中文字幕在线精品人妻| 国产国语一级毛片|