一、前言 JavaScript語言在不同的瀏覽器的下有存在細微的差異,但不像DOM操作差異那麼大,現在為大家列舉出其中一個"for循環"的差異,並介紹如何有效的解決這種差異。
二、問題描述 在下面的測試程式碼例1 中IE6和Chrome輸出的結果是不一致,IE6不執行for語句裡的程式碼
//例1:
alert("準備測試toString是否已被forfor列舉出來")
var forTest = { toString: 1 }
for (i in forTest) {
alert("toString被循環出來")//在IE6下這是不執行的,但是在Chrome執行並輸出結果值「1」
}
三、分析問題 JavaScript中的物件包含了'toString', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable','toLocaleString', 'hasOwnProperty', 'constructor'這7個內建方法。這7個內建方法用for語句是無法列舉出來的。但是IE6和Chrome對內建方法覆蓋的支援不一致。
IE6:雖然 可以內建覆寫 方法,但是 FOR迴圈無法枚舉 出來。
Chrome:可以內建覆寫 方法,FOR循環也能列舉出覆蓋的內建方法。
所以上面的測試代碼例1 中IE6和Chrome瀏覽器輸出結果不一致
四、解決問題 我們要解決上面描述的問題,我們要做二件事情:
使用者使用的瀏覽器是否支援FOR循環枚舉出覆蓋的內建方法
如何優雅的解決不相容問題,使所有的瀏覽器都可以FOR循環枚舉出覆蓋的內建方法
(解法例2)
程式碼如下:
//例2 :
enumerables = true,
forTest = { toString: 1 }
for (i in forTest) {
enumerables = null;
}
if (enumerables) {//這些都是Object物件的屬性,有的瀏覽器(ie6)的for迴圈不會把這些屬性給遍歷出來,所以要手功的把屬性遍歷出來
enumerables = ['hasOwnProperty', 'valueOf', ' isPrototypeOf', 'propertyIsEnumerable',
'toLocaleString', 'toString', 'constructor'];
}
//如果enumerables為null則瀏覽器支援枚舉覆蓋的內建方法,否則只能如下面的程式碼強制的把內建方法複製到新的物件中。
/**
* 所有屬性複製到指定的物件
* @param {Object} object 待合併的物件
* @param {Object} config 來源屬性
* @return {Object} 傳回合併後的對象
*/
function apply(object, config) {
if (object && config && typeof config === 'object') {
var i, j, k ;
//這裡正常的複製物件的方法
for (i in config) {
object[i] = config[i];
}
//相容多瀏覽器把內建的屬性都能重製新的物件
if (enumerables) {
for (j = enumerables.length; j--;) {
k = enumerables[j];
if (config.hasOwnProperty(k)) {//判斷物件是否有某個特定的屬性。必須用字串指定該屬性。 (例如,config.hasOwnProperty("toString"))
object[k] = config[k];
}
}
}
}
return object;
}
複製程式碼
程式碼如下:
//例3:
var a={};
for (i in forTest) {
a[i] = forTest[ i];
}
alert(a.toString) //ie6下複製失敗只能輸入"native code",並不是輸出我們所覆的值var b=apply({},forTest)
alert(b.toString)//使用apply函數,在IE6和Chrome輸出的值都是我們預期想得到的覆蓋值」1“
五、總結
筆者猜測在IE6裡的for語句把那7個內建函數標識到忽略列表,所以怎麼覆蓋也不能在for中枚舉出來,而Chrome就能夠智能的把覆蓋後的內置函數複製出來。
使用解決程式碼 例2 中的apply函數即可解決多瀏覽器下for循環不一致的問題 。
筆者是個菜鳥,也很少寫博客,如果我表達觀點的有錯,或者有筆誤,還請肯請大鳥們糾正錯誤。 六、常見問題 問:為什麼不先判斷瀏覽器的版本是否為IE6,在來設定對應的列舉方案呢? 答:我個人的觀點是,我不確定市場那麼多的瀏覽器(PC機就有N種瀏覽器,還有手機瀏覽器,以後也不知道還有什麼新版本的瀏覽器)分別是用什麼機制的for語制。所以就先測試那的for語句的機制。