在 JavaScript 中有一個非常常用到的函式 for ... in 迴圈,for...in 的用法和 Array.prototype.forEach 很像,但它可以針對**物件(Object)或陣列(Array)**來使用。
for in 針對物件的基本使用
讓我們先來看一下下面這個例子:
var john = { firstName: 'John', lastName: 'Doe' }; for (var prop in john) { console.log(prop + ':' + john[prop]); }
我們建立一個物件名稱為 john,而 prop 是自訂的變數,會把該物件的屬性存在這個變數中,接著讀取下一個屬性,重覆直到沒有屬性為止。透過 for...in,可以把該物件中的所有屬性名稱和屬性值都呼叫出來。
延伸閱讀:for...in @ MDN
可能問題一:包含繼承屬性的物件 - hasOwnProperty
然而,如果我們是透過函式建構式(function constructor)來建立物件時,這個物件可能會繼承該函式建構式的一些屬性或方法,這時候當我們直接使用 for...in 時,這些繼承而來的屬性和方法也會被一併輸出,如下:
// function constructor var Person = function (firstName, lastName) { this.firstName = firstName this.lastName = lastName } // function constructor 的 prototype Person.prototype.getFullName = function () { return this.firstName + ' ' + this.lastName } // 根據 function constructor 所建立的物件 Customer1 var Customer1 = new Person('John', 'Doe') // 透過for...in輸出 for (var prop in Customer1) { console.log(prop + ': ' + Customer1[prop]) }
透過這種方法,我們會發現連同prototype中繼承的方法也被輸出了:
如果想要解決這個問題,我們會需要使用到 Object.prototype.hasOwnProperty 這個內建的函式,透過 obj.hasOwnProperty(prop),它會回傳 Boolean,以此區分這個屬性是直接的或是繼承而來的,也就是說,透過這個方法,它不會往該物件的原型鏈(prototype chain)去檢查。寫法如下:
for (var prop in Customer1) { // 不是繼承而來的屬性,才輸出... if (Customer1.hasOwnProperty(prop)) { console.log(prop + ': ' + Customer1[prop]); } }
如此,我們輸出的結果就只會有 firstName 和 lastName 這兩個直接的屬性。
可能問題二:包含繼承屬性的陣列,儘可能不要使用 for...in
在 JavaScript 中,陣列(Array)也是一種物件,因此,我們也可以對陣列使用 for...in 的方法來輸出陣列的內容,如下:
var arr = ['John', 'Jane', 'Jim'] for (var prop in arr) { console.log(prop + ': ' + arr[prop]) }
如此,我們會得到如下的結果:
然而,當我們使用方括號 [ ] 來建立陣列的時候,其實就和使用 new Array ( ) 是一樣的意思。因此,如果原本的 Array.prototype 有被添加過一些屬性或方法時,使用 for...in 的結果一樣會把這些繼承的屬性和方法給輸出:
Array.prototype.website = 'pjchender' var arr = ['John', 'Jane', 'Jim'] for (var prop in arr) { console.log(prop + ': ' + arr[prop]) }
輸出的結果會把website這個繼承而來的屬性給一併輸出:
為了避免這樣的問題,如果是針對陣列在處理的話,會建議可以使用一般的 for 迴圈來輸出陣列就可以了:
for (var i = 0; i < arr.length; i++) { console.log(i + ': ' + arr[i]) }
因此,當我們在處理陣列資料時,為了避免呼叫出不必要的屬性,應該儘可能不要使用 for...in 的用法來處理迴圈。
var Person = function (firstName, lastName) { this.firstName = firstName this.lastName = lastName } Person.prototype.getFullName = function () { return this.firstName + ' ' + this.lastName } var Customer1 = new Person('John', 'Doe') for (var prop in Customer1) { if (Customer1.hasOwnProperty(prop)) { console.log(prop + ': ' + Customer1[prop]) } } /* ------------------------------------- */ Array.prototype.website = 'pjchender' var arr = ['John', 'Jane', 'Jim'] for (var prop in arr) { console.log(prop + ': ' + arr[prop]) }; for (var i = 0; i < arr.length; i++) { console.log(i + ': ' + arr[i]) }
0 意見:
張貼留言