陣列和物件遍歷方法對比
參考連結:
https://www.cnblogs.com/goloving/p/7680572.html
https://www.jianshu.com/p/c43f418d6bf0
for和for...in對比
var arr = ["a", "b", "c"]; Array.prototype.aaa = function(params) { console.log("aaa"); //0,1,2 } for(let i=0;i<arr.length;i++) { console.log(typeof i); // "0","1","2","aaa" } for(key in arr) { console.log(typeof key); }
1.for..in..輸出的key是字串形式,for是number形式
2.for...in...輸出的是arr上所有可列舉的屬性,包括自身和原型上的
3.for...in...輸出的順序可能不一樣
4.對於不存在的項處理的差異,這一點可以看一個例子
思考: for...in...為什麼沒有輸出陣列原型上的方法(concat,pop等)?我們在擴充套件Array原型的時候有去對比自己新增的屬性與Array原生的屬性有什麼不一樣的地方嗎?
這裡我強調的不一致的地方在於屬性其中的一個特性[[enumberable]],在文章開頭也有特意介紹了一下。如何檢視一個屬性的特性可以使用propertyIsEnumberable()
Object.getOwnPropertyDescriptor()
這兩個方法。
// 檢視原生的方法[[enumberable]]特徵,這裡以splice為例 Array.prototype.propertyIsEnumerable('splice') // false Object.getOwnPropertyDescriptor(Array.prototype, 'splice') // {writable: true, enumerable: false, configurable: true} // 檢視 demo 屬性的特性 Array.prototype.propertyIsEnumerable('aaa') // true Object.getOwnPropertyDescriptor(Array.prototype, 'aaa') // {writable: true, enumerable: true, configurable: true}
從上面的示例程式碼中可以看出,我們新增的aaa方法,預設是可以被for..in枚舉出來的。如果想讓其不被列舉,那麼可以使用ES5的Object.defineProperty()
來定義屬性,此外如果瀏覽器版本不支援ES5的話,我們可以使用hasOwnProperty()
方法在for..in程式碼塊內將可列舉的屬性過濾掉。
var arr = ["a", "b", "c"]; Object.defineProperty(Array.prototype,"aaa",{ value: function (params) { console.log(aaa) }, //enumerable: false, 預設就是不可列舉的 })
hasOwnProperty表示是否有自己的屬性。這個方法會查詢一個物件是否有某個屬性,但是不會去查詢它的原型鏈。
in操作符用於判斷一個物件自身和原型鏈上是否有某個屬性,包括不可列舉的屬性判斷也為true。
var arr = ["a", "b", "c"]; Array.prototype.aaa = function(params) {} console.log(arr.hasOwnProperty('1')); //true console.log(arr.hasOwnProperty('aaa')); //false console.log("aaa" in arr); //true console.log("splice" in arr); //true
for...of...和for...in...對比
1.for in遍歷的是陣列的索引(即鍵名),而for of遍歷的是陣列元素值。
2.for...of...不能遍歷普通的物件,因為普通物件不具備迭代器物件。for..of適用遍歷數/陣列物件/字串/map/set等擁有迭代器物件的集合
object物件keys(), values() entries()
返回一個數組,成員是引數物件自身的(不含繼承的)所有可遍歷( enumerable )屬性的鍵名/鍵值/鍵值對陣列。
返回的是陣列,具備迭代器物件,所以可以用這個方法結合for...of...來進行物件的遍歷。