javascript delete機制學習

想瞭解delete的機制緣起一個現象,我無法解釋,也無法理解。

 

首先看一下下面這個例子:

 

var x = 1;

delete x; //false

然後我又執行瞭一次:

 

y = 2;

delete y; //true

看到上面的結果,我比較吃驚,為什麼同樣是刪除,區別怎麼這麼大呢?進而我想學習和瞭解一下JS delete的機制。

 在MDN(Mozilla Developer Network)上看到下面一個例子

 

x = 42;         // creates the property x on the global object

var y = 43;     // declares a new variable, y

myobj = {

  h: 4,

  k: 5

};

 

delete x;       // returns true  (x is a property of the global object and can be deleted)

delete y;       // returns false (delete doesn't affect variable names)

delete Math.PI; // returns false (delete doesn't affect certain predefined properties)

delete myobj.h; // returns true  (user-defined properties can be deleted)

 

delete myobj;   // returns true  (myobj is a property of the global object, not a variable, so it can be deleted)

我們可以看出,delete元算符執行的結果要麼是true,要麼是false。那麼什麼時候返回true,什麼時間返回false呢?

簡單的總結瞭一句話:隻要可以被刪除,就會返回true(看起來像是一句廢話,可能實際上也是一句廢話)

 

此時我們要討論的就是什麼時候才能被刪除?

 

總結上面的例子我們發現:

1.在global object上的屬性可以被刪除;

2.聲明的變量不能被刪除

3.未聲明的全局變量可以被刪除

4.內置對象的屬性不能被刪除

 

為什麼會有這個結果?

要想知道原理,首先瞭解兩個概念:上下文和屬性特性。

 

1.上下文

我們知道每條語句在執行的時候,他都會處在一個環境中,這個環境就是這條語句的上下文環境。當一個函數執行時,會進入函數代碼執行的上下文;全局代碼執行時,會進入全局代碼執行的上下文。每個執行上下文中都會存在一個內部的可變對象(variable object),當進入這個環境的時候,會實例化這個可變對象,然後聲明的變量和方法,都會作為這個可變對象的屬性。那麼在上述所說到的兩個執行環境就會實例化兩種對象,全局對象(global object)和激活對象(activation object)。

2.屬性特性

ECMAScript5中可以查詢,設置這些特性。我們將存取器屬性的getter,setter方法看成是屬性的特性,同理,可以把數據屬性的值看做屬性的特性。所以可認為一個屬性包含一個名字和4個特性(見下表)。 ECMACScript5定義瞭一個名為“屬性描述符”的對象。這個對象代表那4個特性。通過Object.getOwnPropertyDescriptor(object, propertyname)可以獲得某個對象特定屬性的屬性描述符。

特性名

說明

Configurable

設置屬性是否可配置,即能否更改(包括名值)或者刪除(delect)它,能否修改屬性特性等等

Enumerable

設置屬性是否可以枚舉,即能否通過for-in循環返回

Writable

是否可寫

Value

就是屬性值,對象在讀取屬性值時就是從這個位置讀取的.

這裡delete會涉及到Configurable特性。可通過上述方法getOwnPropertyDescriptor簡單判斷是否可以delete。開始說的兩個例子的結果如下:

 

var x = 1;

Object.getOwnPropertyDescriptor(window, 'x'); //configurable= false

delete x; //false

y = 2;

Object.getOwnPropertyDescriptor(window, 'y'); //configurable= true

delete y; //true

這裡還需要交代的是,屬性的特性是在創建的時候就確定的,賦值並不能改變它的特性,

 

function sum() {}

sum = 1;

Object.getOwnPropertyDescriptor(window, 'sum'); //configurable= false

delete sum; //false

但是可以通過這個方法定義的特性值Object.defineProperties(object, descriptors),

 

Object.defineProperties(window, {sum1:{value:1,configurable:true}});

Object.getOwnPropertyDescriptor(window, 'sum'); //configurable= true

delete sum1; //true

Object.defineProperties(window, {sum2:{value:1,configurable:false}});

Object.getOwnPropertyDescriptor(window, 'sum'); //configurable= false

delete sum2; //false

 

總結一下delete不能刪除屬性:

 

1.聲明的變量(變量、函數、函數參數)不能刪除;如:var x=1;

2.內置對象的屬性不能刪除;如:Math.PI

3.定義的變量屬性的configurable值為false的,不能刪除。

 

 

發佈留言