一、前言 JavaScript語言在不同的浏覽器的下有存在細微的差異,但不像DOM操作差異那麼大,現在為大家列舉出其中一個"for循環"的差異,並介紹如何有效的解決這種差異。
二、問題描述 在下面的 測試代碼 例1 中IE6和Chrome輸出的結果是不一致,IE6不執行for語句裡的代碼
復制代碼 代碼如下:
//例1:
alert("准備測試toString是否被for循環枚舉出來")
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)
復制代碼 代碼如下:
//例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語句的機制。