JS 对兼容性方法的效率考虑和选择

今天看书自己写例子,碰到了一个问题。

由于 Array.every 是 ECMAScript 5 定义的方法,需要 IE 9+、FireFox 2+、Opera 9.5+、Safari 3+ 和 Chrome* 的浏览器版本支持,在考虑到兼容性的时候需要兼容性写法:

// 定义方式 1var hs = {

    // 这是一个Array的工具类, 用以编写兼容性方法

    ArrayUtil: {

        every: function(arr, func) {
            // 对参数的检测省略...

            if (Array.every) {  // 优先使用原生方法
                return arr.every(func);
            } else {        // 否则使用兼容方法
                var result = false;

                for(var i=0,len=arr.length; i<len; i++) {
                    result = func(arr[i], i, arr);
                    if (result === false) {
                        return false;
                    }
                }

                return true;
            }
        }

        // 其他兼容性方法省略...
    }
}

这样就可以实现对低版本浏览器(比如IE6)的兼容。

但这种定义方式使得 every 方法存在一个问题,就是它在每次被调用执行的时候都会进行重复的判断——浏览器是否支持原生的 Array.every?浏览器是否支持原生的 Array.every?浏览器是否支持原生的 Array.every?……哪怕得到的永远是同一个答案……

如果这个兼容性方法只是偶尔调用,那重复的判断也不是什么大问题。

但如果这个方法被频繁调用,重复的判断造成的性能浪费就不能忽视了。

于是就有了下面的定义方式:

// 定义方式 2var hs = {

    ArrayUtil: {

        every: function() {    // 这是一个自调函数, 在(对象)方法创建之处就进行兼容性判断, 只保留一个选择,这个选择就构成了 every 方法的全部内容。

            if (Array.every) {
                retrun function(arr, func) {
                    return arr.every(func);      // 原来的执行代码被包裹在函数里, 而这个函数将被自调函数返回,并赋值给every。
                };
            } else {
                return function(arr, func) {
                    var result = false;

                    for(var i=0,len=arr.length; i<len; i++) {
                        result = func(arr[i], i, arr);
                        if (result === false) {
                            return false;
                        }
                    }

                    return true;
                };
            }
        }()
    }
}

这样,仅有的一次判断只会在对象(方法)创建时进行一次,every 保留唯一一个方法,在被调用执行时不会再进行重复而无意义的判断。

这种方式使程序变得更简洁、运行也更快速(哪怕只是一点,但这是量的积累)。

然而,它也不是全无缺点的,它的问题体现在代码首次加载(或程序初始化)的时候:

如果是个人网站、轻量代码,它“一步到位”的优点会显露无疑;

但在面对门户网这类大型网站、在面对大量代码(需要进行大量兼容性判断)的时候,它的“一次性”会让你的程序执行显得拖沓和吃力。

所幸这问题也不是无法避免的,我们可以对程序进行“分流”处理:对程序里的兼容性方法还是选用一次性判断的方式,但这“一次性”不再扎堆于程序初始化,而是分流于方法初次调用时——在方法被明确调用的时候才进行唯一一次判断。

// 定义方式 3
var hs = {

    ArrayUtil: {

        every: function(arr, func) {

            if (Array.every) {
                this.every = function(arr, func) {        // 重新赋值
                    return arr.every(func);
                };
            } else {
                this.every = function(arr, func) {        // 重新赋值
                    var result = false;

                    for(var i=0,len=arr.length; i<len; i++) {
                        result = func(arr[i], i, arr);
                        if (result === false) {
                            return false;
                        }
                    }

                    return true;
                };
            }
            return this.every(arr, func);                    // 方法第一次调用并重新赋值以后执行一次,确保这首次调用能有结果。
        }
    }
}    

这就解决了问题,只在方法被用到的时候才进行一次判断,不影响对象构建、程序初始化的速度。

相比于第二种方式,这种方式在第一次调用方法时也会损失一些性能,但就整个程序的性能来说,这已经是最佳选择。

三种定义方式各有优缺点,不同使用环境:

兼容性方法偶尔使用,选方式 1

兼容性方法频繁使用,但量少,选方式 2

兼容性方法频繁使用,且量大,选方式 3

另外,在各种情况下都能表现良好和稳妥的,是方式 3

时间: 2024-08-18 00:16:01

JS 对兼容性方法的效率考虑和选择的相关文章

JS添加节点方法与JQuery添加节点方法的比较及总结

原生JS添加节点方法与JQuery添加节点方法的比较及总结 一.首先构建一个简单布局,来供下边讲解使用 1.HTML部分代码: <div id="div1">div1</div> <div id="div2">div2 <span id="span1">span1</span> <span id="span2">span2</span> <

[转载]JS浏览器兼容性问题

from:http://dada-fangfang.iteye.com/blog/811749 做BS开发就难免会用到javascript,而每个浏览器对javascript的支持有不同.这就需要我们程序员去兼容他们,不然有些浏览器就无法运行我们的代码.就会造来客户的投诉,如果让BoSS知道了,这可不太好哦.下面是兼容IE和FF的js脚本做法和分解(部分选自网上):   .以下以 IE 代替 Internet Explorer,以 MF/FF 代替 Mozzila Firefox  //wind

原始JS选择器使用方法总结

原始JS选择器使用方法总结 常见的getElementById,getElementsByName,getElementsByTagName.但外国人不满意这些 API,于是搞出了getElementsByClassName,后来一点点又出现了jQuery选择器,这里只说原始js选择器. 1.getElementById 这是最常用的选择器,通过id来定位: 例: var test=document.getElementById("test").value;//获取文档中id为test

原生JS添加节点方法与JQuery添加节点方法的比较及总结

一.首先构建一个简单布局,来供下边讲解使用 1.HTML部分代码: <div id="div1">div1</div> <div id="div2">div2 <span id="span1">span1</span> <span id="span2">span2</span> </div> <div id="div

js面向对象+一般方法的选项卡

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

JQuery 加载 CSS、JS 文件的方法有哪些?

在进行web前端开发(http://www.maiziedu.com/course/web-px/)时,我们可能会需要使用JQuery加载一个外部的css文件或者js文件,加载外部文件的方法有多种,下面具体看看各种加载方法 JS 方式加载 CSS.JS 文件: //加载 css 文件function includeCss(filename) { var head = document.getElementsByTagName('head')[0]; var link = document.cre

js 变量提升+方法提升

<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> var a = 100; function t() { alert(a); var a = 10; } t(); //输出结果为undefine

【js常用DOM方法】

介绍几个js DOM的常用方法 获取元素节点 getElementById  getElementsByTagName  getElementsByClassName 先写一个简单的网页做测试: /* test.html*/<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>test</title> </head> <body&g

C#的WEBBROWSER与JS交互的方法(转载)

原地址:http://www.jb51.net/article/57574.htm 本文实例总结了C#的WEBBROWSER与JS交互的方法.分享给大家供大家参考.具体实现方法如下: 一.实现WebBrowser内部跳转,阻止默认打开IE 1.引用封装好的WebBrowserLinkSelf.dll实现 复制代码代码如下: public partial class MainWindow : Window{       private WebBrowser webBrowser = new Web