js中for in 可以遍歷對象或數組的顯性屬性,也就是說我們自己定義的屬性是可以遍歷的,那些原型上默認已有的屬性,例如:Object.prototype.toString、Object.prototype.hasOwnProperty 是遍歷不出來的。
for in 的基本規則如上,不過還有“坑”的地方需要我們注意:
1、for in循環出的值不一定是按順序的。代碼如下:
var b = {3:1,42:2,11:3} for( var key in b ){ alert( b[key] ) }
低版本瀏覽器彈窗的順序是:1、2、3。現代瀏覽器彈窗的順序是1、3、2。
2、在原型上加擴展方法,會被for in 出來。代碼如下:
Object.prototype.test = "I am test" var b = {"name":"txj"} for( var key in b ){ alert(key + " : "+ b[key]) }
我們手動加在原型上的方法,for in的時候會被遍歷出來。一般我們遍歷對象並不需要其原型的屬性,所以遍歷時最好Object.prototype.hasOwnProperty方法進行判斷。
3、在實例中定義原型中已有的方法,瀏覽器for in 情況不一致。代碼如下:
var b = {"name":"txj"} b.toString = function(){ alert("I am toString") } for( var key in b ){ alert(key + " : "+ b[key]) }
我們給b實例加了一個原型上已有的方法toString。現代瀏覽器能循環出toString 低版本瀏覽器卻不能。所以給實例定屬性名時,不要和原型已有的一致。
4、各瀏覽器循環出的屬性順序不同。代碼與2中的一樣:
Object.prototype.test = "I am test" var b = {"name":"txj"} for( var key in b ){ alert(key + " : "+ b[key]) }
現代瀏覽器先循環實例中的屬性,再循環原型中的屬性。低版本瀏覽器相反。
這讓我想到了jQuery對$.isPlainObject()方法實現的一段代碼:
// Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key for ( key in obj ) {} return key === undefined || hasOwn.call( obj, key );
它這里說如果一個對象的最后一個屬性是實例自己的屬性,那么所有的屬性都是實例自己的屬性。這對低版本瀏覽器來說應該是不對的。所以jquery后來又加了如下代碼修復:
// Support: IE<9 // Handle iteration over inherited properties before own properties. if ( support.ownLast ) { for ( key in obj ) { return hasOwn.call( obj, key ); } }
最后想吐槽一下,一般不要在原型上加自定義方法;數組的循環一般不用for in 。哈哈!
