zoukankan      html  css  js  c++  java
  • jQuery Utilities分类下的函数的实现方式分析

    这里更给出的实现都是简化的版本,没有考虑性能优化、异常处理和某些特殊情况。实际上,jQuery的完整实现完全可以自己在未压缩版的源代码(这里分析 的版本是 jQuery 1.6)中 search,因为这里主要讲解实现思路,作为引导和参考,所以下面的分析中将忽略一些次要因素,以避免冲淡主题。

    jQuery.globalEval()

      通常情况下使用 eval,this 所指向的都是当前对象;有的时候我们希望  this 指向全局对象( window ),就可以使用 jQuery.globalEval() 了。这在动态加载外部 JavaScript 文件并执行时十分有用。

      功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    a = {
        func : function() {
            eval("alert(this === window)");
        },
        globalFunc: function() {
            $.globalEval("alert(this === window)");
        }
    }

    a.func();     // alert( flase )
    a.globalFunc();    // alert( true )
    </script>

    可以看到,通常情况下调用附加在对象上的函数,并在函数中使用 eval() 时, this 并不指向 window;但如果使用 globalEval() ,那么 this 就会指向 window 。

    简单的实现方式如下:

    $ = {
        globalEval: function(data) {
            (function() { eval(data); }())
        }
    }

    在匿名函数内使用 eval 。由于匿名函数不指向任何一个对象,因此其指向的对象也就是全局对象( window )了。jQuery 的源代码中还先检查了 window.execScript 是否存在,如果存在则优先使用 window.execScript 。

    jQuery.parseJSON() 与 jQuery.parseXML()

      jQuery 与后台的数据交互最好采用某种规范的格式,经常使用的就是 JSON 和 XML 格式了。从后台得到的数据通常是字符串,还需要将字符串转为 JavaScript 对象,这也就是 jQuery.parJSON() 和 jQuery.parseXML() 的功能了。

      jQuery.parseJSON() 的功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    obj = $.parseJSON('{ "s": "string value", "i": 1234 }');
    document.write('obj.s = ' + obj.s);
    document.write('<br />');
    document.write('obj.i = ' + obj.i);
    </script>

    显示结果如下:

    obj.s = string value淘宝女装夏装新款
    obj.i = 1234

    jQuery.parseXML() 的功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    str = "<root><customer name='John'></customer></root>";
    xml = $.parseXML(str);

    customer = xml.getElementsByTagName ("customer")[0];
    name = customer.getAttribute ("name");
    document.write("customer.name = "+ name);
    </script>

    显示结果如下:

    customer.name = John

    这两个函数的简单实现如下:

    $ = {
        parseJSON: function(data) {
            return new Function("return " + data)();
        },

        parseXML : window.DOMParser ?
        function(data) {
            var parser = new DOMParser();
            return parser.parseFromString(data, "text/xml");
        } :
        function(data) {
            xml = new ActiveXObject("Microsoft.XMLDOM");
            xml.async = "false";
            xml.loadXML(data);
            return xml;
        }
    }

    parseJSON() 只需要直接创建一个 Function ,并将内容设置为 "return " + data 就可以了。这类似于 eval 。因为 JSON 本身就是 JavaScript 的对象(或数组)的格式,因此转换起来异常简单。同样地,jQuery 的源代码中优先检查了 window.JSON.parse ,如果存在则使用浏览器内置的解析器。虽然可能在性能上略有提升,但也可能导致不同浏览器中的解析行为有所不同(通常我会把这个检查注释掉)。
      parseXML() 需要分两种情况,大多数浏览器都可以使用 DOMParser 进行解析,但 IE 中需要使用 ActiveXObject。jQuery 源代码中还有一些抛出 error 的处理。

    jQuery.trim()

      jQuery.trim() 函数用于去除字符串中的空白字符。

      功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    alert($.trim('    aaaa\r\n\t'));    // aaaa
    </script>

    我们可以用正则表达式实现这个功能:

    $ =  {
        trim : function(text) {
            return text == null ? '' :
                text.toString()
                    .replace(/^\s+/, '')
                    .replace(/\s+$/, '');
        }
    };

    jQuery的源代码中还对 String.prototype.trim 进行检查,如果浏览器本身支持这个函数,就优先使用浏览器自带的 trim 函数。

    jQuery.isFunction()

      该函数用于检查一个变量是否用于表示一个函数的引用。

      功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    function a() {}
    alert($.isFunction(a));    // true
    </script>

    实现方式如下:

    $ = function(){
        // implemention of class2type and type(obj) ...

        return {
            isFunction: function( obj ) {
                return type(obj) === "function";
            }
        }
    }();

    jquery.isEmptyObject()

      该函数用于检查一个对象是否为空对象。

      功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    a = {}
    alert($.isEmptyObject(a));    // true
    </script>

    实现方式如下:

    $ = {
        isEmptyObject: function(obj) {
            for (var name in obj) {
                return false;
            }
            return true;
        }
    };

    jQuery.isXMLDoc()

      该函数用于检查一个对象是否表示一个 XML 文档。

      功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    str = "<root><customer name='John'></customer></root>";
    xml = $.parseXML(str);

    customer = xml.getElementsByTagName ("customer")[0];
    name = customer.getAttribute ("name");
    document.write("customer.name = "+ name);
    </script>

    简单实现如下:

    $ = {
        // parseXML : ...,
        isXMLDoc: function( elem ) {
            var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
            return documentElement ? documentElement.nodeName !== "HTML" : false;
        }
    };

    parseXML() 的实现请参考之前的分析。
      isXMLDoc() 的实现方式为检查元素的 documentElement 是否存在,存在且不为 HTML ,则表示这是一个 XML 文档。

    jQuery.contains()

      检查一个 DOM Element 是否包含了另一个 DOM Element。

      功能测试代码如下:

    <div id="a">
        <div id="b" />
    </div>

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    window.onload = function() {
        var a = document.getElementById('a');
        var b = document.getElementById('b');
       
        alert($.contains(a, b)); // true
        alert($.contains(b, a)); // false
    }
    </script>

    简单实现如下:

    $ = {
        contains: document.documentElement.contains ?
        function(a, b) {
            return a !== b && (a.contains ? a.contains(b) : true);
        } :
        function(a, b) {
            return !!(a.compareDocumentPosition(b) & 16);
        }
    }

    根据不同浏览器的支持情况,借助浏览器内置的 contains() 或 compareDocumentPosition() 函数来实现这个功能。

    jQuery.inArray()

      命名为 indexOf 可能会更合适些。返回一个元素在数组中的序号,不存在则返回  -1 。

      功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    alert( $.inArray( 3, [1, 2, 3, 4] ) );    // 2
    alert( $.inArray( 5, [1, 2, 3, 4] ) );    // -1
    </script>

    简单实现如下:

    $ = {
        inArray: function(elem, array) {
            for (var i = 0, length = array.length; i < length; i++) {
                if (array[i] === elem) {
                    return i;
                }
            }
            return -1;
        }
    };

    遍历数组,检查是否包含所查找的元素,找到则返回对应的序号,否则返回 -1。除了数组,也可以用于遍历 “类数组”的对象,如 {0:"aaa", 1: "bbb", length: 2}, 函数调用时的隐藏变量 “arguments” 就是典型的“类数组”对象。
      jQuery 源代码的实现中,在浏览器支持 Array.prototype.indexOf 的情况下,会优先采用浏览器自带的 indexOf 函数。

    jQuery.merge()

      合并两个数组或“类数组”的对象( arguments 就是典型的“类数组”)。
      功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    a = ['aaa', 'bbb'];
    b = ['ccc', 'ddd'];
    $.merge(a, b);

    for (i in a) {
        alert(a[i]); // aaa, bbb, ccc, ddd
    }


    a = ['aaa', 'bbb'];
    b = {0: 'ccc', 1: 'ddd'}
    $.merge(a, b);

    for (i in a) {
        alert(a[i]); // aaa, bbb, ccc, ddd
    }
    </script>

    简单实现如下:

    $ = {
        merge : function(a, b) {
            for (var i = a.length, j = 0; b[j] !== undefined; ++i, ++j) {
                a[i] = b[j];
            }
            a.length = i;
            return a;
        }
    }

    jQuery 的源代码中的分类更详细些,数组用  for (i = 0; i < leng; ++i) 的方式进行遍历。这可能也是一种性能优化吧,不过实际上并不必要。

    jQuery.makeArray()

      将单个对象或“类数组”对象转为数组。
      功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    a = $.makeArray('aaa');
    a.push('bbb');
    alert(a)    // aaa, bbb

    b = $.makeArray({0:'aaa', 1:'bbb', length: 2});
    b.push('ccc');

    alert(b)    /// aaa, bbb, ccc
    </script>

    简单实现如下:

    $ = function(){
        // implemention of class2type, type(obj), isWindow(obj), merge(a, b) ...

        function makeArray(array) {
            var ret = [];
            if ( array != null ) {
                var t = type(array);
                if ( array.length == null || t === "string" || t === "function" || t === "regexp" || isWindow(array) ) {
                    ret.push(array);
                } else {
                    merge(ret, array);
                }
            }
       
            return ret;
        };

        return { merge: merge, makeArray: makeArray }
    }();

    jQuery.each()

      该函数提供一种遍历数组和对象的函数,支持传入一个回调函数,在遍历过程中执行。
      功能测试代码如下:

    <script type="text/javascript" src="jquery.js"></script>
    <script>
    a = ['aaa', 'bbb'];
    $.each(a, function(i, value){
        alert('a[' + i + '] = ' + value);    // a[0] = aaa, a[1] = bbb
    })

    b = {a: 'aaa', b: 'bbb'}
    $.each(b, function(name, value){
        alert('b.' + name + ' = ' + value);    // b.a = aaa, b.b = bbb
    })
    </script>

    简单实现如下:

    $ = {
        each : function(obj, callback) {
            for (var n in obj ) {
                if (callback.call(obj[n], n, obj[n]) === false) {
                    break;
                }
            }
        }
    };

  • 相关阅读:
    node基础(2)
    node基础知识(1)
    面试题1
    HTML5中的表单属性
    H5中元素的拖放
    Niagara基于javascript的控件开发
    CSS居中
    2018-3-21 url 、href、src
    2018-3-7 色彩的一些知识
    JS基本数据类型
  • 原文地址:https://www.cnblogs.com/sky7034/p/2048520.html
Copyright © 2011-2022 走看看