2016年6月29日 星期三

[筆記] 談談JavaScript中 for ... in 這個 function


在JavaScript中有一個非常常用到的函式 for ... in 這個迴圈,for...in 的用法和 foreach 很像,但是在JavaScript中它可以針對物件或陣列來使用。

for in 針對物件的基本使用


讓我們先來看一下下面這個例子:

var john = {
    firstname: 'John',
    lastname: 'Doe'
};

for(var prop in john){
         
    console.log(prop + ':' + john[prop]);
     
}


我們建立一個物件名稱為john,而 prop 是自訂的變數,會把該物件的屬性存在這個變數中,接著讀取下一個屬性,重覆直到沒有屬性為止。透過for in,我們就可以把該物件中的所有屬性和名稱都呼叫出來。


問題一:包含繼承屬性的物件 - 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中繼承的方法也被輸出了:


如果想要解決這個問題,我們會需要使用到 hasOwnProperty 這個內建的函式,透過hasOwnProperty我們可以區分這個屬性是直接的或是繼承而來的,也就是說,透過這個方法,它不會往該物件的原型鏈(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]);

}


→回到此系列文章目錄


Share:

0 意見:

張貼留言