寫js的時候需要遍歷一個對象的屬性,把屬性名和屬性值都提出來,之前沒遇到這種需求,查了一下可以用for in的方式.
var obj = { "key1":"value1", "key2":"value2", "key3":"value3" }; function EnumaKey(){ for(var key in obj ){ alert(key); } } function EnumaVal(){ for(var key in obj ){ alert(obj[key]); } }
數組也可以這樣遍歷,但不推薦,因為不能保證順序,而且如果在Array的原型上添加了屬性,這個屬性也會被遍歷出來。
for-in循環應該用在非數組對象的遍歷上,使用for-in進行循環也被稱為“枚舉”。
從技術上將,你可以使用for-in循環數組(因為JavaScript中數組也是對象),但這是不推薦的。因為如果數組對象已被自定義的功能增強,就可能發生邏輯錯誤。另外,在for-in中,屬性列表的順序(序列)是不能保證的。所以最好數組使用正常的for循環,對象使用for-in循環。
有個很重要的hasOwnProperty()方法,當遍歷對象屬性的時候可以過濾掉從原型鏈上下來的屬性。
思考下面一段代碼:
// 對象 var man = { hands: 2, legs: 2, heads: 1 }; // 在代碼的某個地方 // 一個方法添加給了所有對象 if (typeof Object.prototype.clone === "undefined") { Object.prototype.clone = function () {}; }
在這個例子中,我們有一個使用對象字面量定義的名叫man的對象。在man定義完成后的某個地方,在對象原型上增加了一個很有用的名叫 clone()的方法。此原型鏈是實時的,這就意味着所有的對象自動可以訪問新的方法。為了避免枚舉man的時候出現clone()方法,你需要應用hasOwnProperty()方法過濾原型屬性。如果不做過濾,會導致clone()函數顯示出來,在大多數情況下這是不希望出現的。
// 1. // for-in 循環 for (var i in man) { if (man.hasOwnProperty(i)) { // 過濾 console.log(i, ":", man[i]); } } /* 控制台顯示結果 hands : 2 legs : 2 heads : 1 */ // 2. // 反面例子: // for-in loop without checking hasOwnProperty() for (var i in man) { console.log(i, ":", man[i]); } /* 控制台顯示結果 hands : 2 legs : 2 heads : 1 clone: function() */
另外一種使用hasOwnProperty()的形式是取消Object.prototype上的方法。像這樣:
for (var i in man) { if (Object.prototype.hasOwnProperty.call(man, i)) { // 過濾 console.log(i, ":", man[i]); } }
其好處在於在man對象重新定義hasOwnProperty情況下避免命名沖突。也避免了長屬性查找對象的所有方法,你可以使用局部變量“緩存”它。
var i, hasOwn = Object.prototype.hasOwnProperty; for (i in man) { if (hasOwn.call(man, i)) { // 過濾 console.log(i, ":", man[i]); } }
嚴格來說,不使用hasOwnProperty()並不是一個錯誤。根據任務以及你對代碼的自信程度,你可以跳過它以提高些許的循環速度。但是當你對當前對象內容(和其原型鏈)不確定的時候,添加hasOwnProperty()更加保險些。
--------------------------------------------------------------------------------------------------------------------------------------------------------------
javascript中in關鍵字還有下面的作用
定義:
in操作符用來判斷某個屬性屬於某個對象,可以是對象的直接屬性,也可以是通過prototype繼承的屬性。(參見hasOwnProperty)
注意事項:
對於一般的對象屬性需要用字符串指定屬性的名稱
如:
var mycar = {make: "Honda", model: "Accord", year: 1998};
"make" in mycar // returns true
"model" in mycar // returns true
對於數組屬性需要指定數字形式的索引值來表示數組的屬性名稱(固有屬性除外,如length)。
// Arrays
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
0 in trees // returns true
3 in trees // returns true
6 in trees // returns false
"bay" in trees // returns false (you must specify the index number,
// not the value at that index)
"length" in trees // returns true (length is an Array property)
in的右邊必須是一個對象,如:你可以指定一個用String構造器生成的,但是不能指定字符串直接量的形式:
var color1 = new String("green");
"length" in color1 // returns true
var color2 = "coral";
"length" in color2 // generates an error (color is not a String object)
如果你使用delete操作符刪除了一個屬性,再次用in檢查時,會返回false,如:
var mycar = {make: "Honda", model: "Accord", year: 1998};
delete mycar.make;
"make" in mycar; // returns false
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
delete trees[3];
3 in trees; // returns false
如果你把一個屬性值設為undefined,但是沒有使用delete操作符,使用in檢查,會返回true.
var mycar = {make: "Honda", model: "Accord", year: 1998};
mycar.make = undefined;
"make" in mycar; // returns true
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
trees[3] = undefined;
3 in trees; // returns true