zoukankan      html  css  js  c++  java
  • JavaScript在多浏览器下杂谈1for循环

    目录

    一、前言
    五、总结

    一、前言

    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浏览器输出结果不一致

    四、解决问题

    我们要解决上面描述的问题,我们要做二件事情:

    1. 用户使用的浏览器是否支持 FOR循环枚举出覆盖的内置方法
    2. 如何优雅的解决不兼容问题,使所有的浏览器都可以 FOR循环枚举出覆盖的内置方法
    3. (解决代码   例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“

    五、总结

    1. 笔者猜测在IE6里的for语句把那7个内置函数标识到忽略列表,所以怎么覆盖也不能在for中枚举出来,而Chrome就能够智能的把覆盖后的内置函数复制出来。
    2. 使用解决代码  例2 中的apply函数即可解决多浏览器下for循环不一致的问题 。

    笔者是个菜鸟,也很少写博客,如果我表达观点的有错,或者有笔误,还请肯请大鸟们纠正错误。

    六、常见问题

    • 问:为什么不先判断浏览器的版本是否为IE6,在来设置对应的枚举方案呢?
      答:我个人的观点是,我不确定市场那么多的浏览器(PC机就有N种浏览器,还有手机浏览器,以后也不知道还有什么新版本的浏览器)分别是用什么机制的for语制。所以就先测试那的for语句的机制。
  • 相关阅读:
    【JAVA SE基础篇】28.面向对象三大特征之多态
    【JAVA SE基础篇】27.面向对象三大特征之封装
    【JAVA SE基础篇】26.toString()方法和equlas()方法
    【JAVA SE基础篇】25.面向对象三大特征之继承
    【JAVA SE基础篇】24.包的机制和import详解
    ssh框架文件上传下载
    java格式化时间格式
    表单提交后打印后台传过来的数据
    使用ajaxfileupload.js实现文件上传
    JSTL跳出<c:forEach>循环
  • 原文地址:https://www.cnblogs.com/lmm0591/p/2753452.html
Copyright © 2011-2022 走看看