JavaScript delete操作符&&javascript中數組元素刪除問題的討論

delete 運算符 
從對象中刪除一個屬性,或從數組中刪除一個元素。 
delete expression 
expression 參數是一個有效的 JScript 表達式,通常是一個屬性名或數組元素。 
說明 
如果 expression 的結果是一個對象,且在 expression 中指定的屬性存在,而該對象又不允許它被刪除,則返回 false。 
在所有其他情況下,返回 true。 
從數組中刪除一個元素,只能刪除那個元素的值,而不是元素本身。不過從對象中刪除一個屬性是可以的。 
Javascript的變量 
實際上Javascript中,變量 = 對象屬性,這是因爲 Javascript 在執行腳本之前會創建一個Global對象,所有的全局變量都是這個Global對象的屬性,執行函數時也會創建一個Activation對象,所有的局部變量都是這個Activation對象的屬性。如下例: 
複製代碼代碼如下:

var global = 42; 
this.global; // 42, 可以通過this來訪問Global對象 
this.global2 = 12; 
global2; // 12 
function foo() { 
var local = 36; 
// 不過無法直接訪問Activation, 
// 因此無法通過 foo.local 的方式來訪問local變量 
}

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

// C++ 
class Object { 
public: 
Object *x; 

Object o; 
o.x = new Object(); 
delete o.x; // 上一行new的Object對象將被釋放

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

// Javascript 
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"],兩者效果相同。 
對變量執行delete的情況 
由於變量也是 Global 或者是 Activation 對象的屬性,所以對變量的delete操作也是同樣的結果。 
複製代碼代碼如下:

var global = 42; 
delete global; // 刪除Global.global 
function foo() { 
var local = 36; 
delete local; // 刪除Activation.local 
}

能刪除的屬性和不能刪除的屬性 
並不是所有的屬性都能被delete。例如,prototype中聲明的屬性就無法被delete: 
複製代碼代碼如下:

function C() { this.x = 42; } 
C.prototype.x = 12; 
var o = new C(); 
o.x; // 42, 構造函數中定義的o.x 
delete o.x; 
o.x; // 12, prototype中定義的o.x,即使再次執行delete o.x也不會被刪除

對象的預定義屬性也無法刪除。 可以認爲這類屬性帶有DontDelete的特性。 
複製代碼代碼如下:

var re = /abc/i; 
delete re.ignoreCase; 
re.ignoreCase; // true, ignoreCase無法刪除

能刪除的變量和不能刪除的變量 
通過function聲明的函數擁有DontDelete特性,無法被刪除。 
複製代碼 
function foo() { return 42; } 
delete foo; 
foo(); // 42

但是有一點例外,就是通過 eval 執行的代碼中,通過var聲明的變量雖然與正常的var聲明變量同屬於Global對象,但它們不具有DontDelete特性,能被刪除。 
複製代碼代碼如下:

eval("var x = 36;"); 
x; // 42 
delete x; 
x; // undefined

但是這也有一點例外,eval的代碼中的函數內通過var定義的變量具有DontDelete,不能被刪除。 
複製代碼代碼如下:

eval("(function() { var x = 42; delete x; return x; })();"); 
// 返回 42

delete的返回值 
delete是普通運算符,會返回true或false。規則爲:當被delete的對象的屬性存在並且擁有DontDelete時返回false,否則返回true。這裏的一個特點就是,對象屬性不存在時也返回true,所以返回值並非完全等同於刪除成功與否。 
複製代碼代碼如下:

function C() { this.x = 42; } 
C.prototype.y = 12; 
var o = new C(); 
delete o.x; // true 
o.x; // undefined 
"x" in o; // false 
// o.x存在並且沒有DontDelete,返回true 
delete o.y; // true 
o.y; // 12 
// o自身沒有o.y屬性,所以返回true 
// 從這裏也可以看到prototype鏈的存在,對象自身屬性和prototype屬性是不同的 
delete o; // false 
// Global.o擁有DontDelete特性所以返回false 
delete undefinedProperty; // true 
// Global沒有名爲undefinedProperty的屬性因此返回true 
delete 42; // true 
// 42不是屬性所以返回true。有的實現會拋出異常(違反ECMAScript標準) 
var x = 24; 
delete x++; // true 
x; // 25 
// 被刪除的是x++的返回值(24),不是屬性,所以返回true                                                                                       

javascript中數組元素刪除問題的討論:

var arr=['a','b','c'];

若要刪除其中的'b',有兩種方法:

1.delete方法:delete arr[1]

這種方式數組長度不變,此時arr[1]變爲undefined了,但是也有好處原來數組的索引也保持不變,此時要遍歷數組元素可以才用

for(index in arr)

alert('arr['+index+']='+arr[index]);

這種遍歷方式跳過其中undefined的元素

* 該方式IE4.o以後都支持了

2.數組對象splice方法:arr.splice(1,1);

這種方式數組長度相應改變,但是原來的數組索引也相應改變

splice參數中第一個1,是刪除的起始索引(從0算起),在此是數組第二個元素

第二個1,是刪除元素的個數,在此只刪除一個元素,即'b';

此時遍歷數組元素可以用普通遍歷數組的方式,比如for,因爲刪除的元素在

數組中並不保留

* 該方法IE5.5以後才支持

值得一提的是splice方法在刪除數組元素的同時,還可以新增入數組元素

比如arr.splice(1,1,'d','e'),d,e兩個元素就被加入數組arr了

結果數組變成arr:'a','d','e','c' 

<big>外一篇:</big>

JavaScript通過設置數組的length屬性來截斷數組是惟一一種縮短數組長度的方法.如果使用delete運算符來刪除數組中元素,雖然那個元素變成未定義的,但是數組的length屬性並不改變兩種刪除元素,數組長度也改變的方法.

  /*
  * 方法:Array.remove(dx)
  * 功能:刪除數組元素.
  * 參數:dx刪除元素的下標.
  * 返回:在原數組上修改數組
  */
  
 //經常用的是通過遍歷,重構數組.
 Array.prototype.remove=function(dx)
 {
  if(isNaN(dx)||dx>this.length){return false;}
  for(var i=0,n=0;i<this.length;i++)
  {
    if(this[i]!=this[dx])
    {
      this[n++]=this[i]
    }
  }
  this.length-=1
 }
 a = ['1','2','3','4','5'];
 alert("elements: "+a+"nLength: "+a.length);
 a.remove(0); //刪除下標爲0的元素
 alert("elements: "+a+"nLength: "+a.length);
  
 /*
  * 方法:Array.baoremove(dx)
  * 功能:刪除數組元素.
  * 參數:dx刪除元素的下標.
  * 返回:在原數組上修改數組.
  */
  
 //我們也可以用splice來實現.
  
 Array.prototype.baoremove = function(dx)
 {
  if(isNaN(dx)||dx>this.length){return false;}
  this.splice(dx,1);
 }
 b = ['1','2','3','4','5'];
 alert("elements: "+b+"nLength: "+b.length);
 b.baoremove(1); //刪除下標爲1的元素
 alert("elements: "+b+"nLength: "+b.length);


                                         
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章