jQuery源码剖析--jQuery入口函数-init实现

来源:互联网 发布:视频短片软件 编辑:程序博客网 时间:2024/06/05 13:42

通过$工厂,最终到达了init构造函数,所有实例的初始化过程都在这里实现,所以把这里称之为入口函数。

jQuery入口函数-init实现:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body><div>    <a class="a">1</a>    <a class="a">2</a>    <a class="a">3</a>    <a class="a">4</a></div><script>    /*     * jq入口对不同参数处理的规律:     * 1、传入null、undefined、0、NaN、''返回空对象( 即空实例 )     * 2、传入字符串,那么需要判断是html片段 还是 其它,     * 如果是片段,则创建对应的DOM,然后添加到实例身上;     * 否则按照选择器获取页面中的DOM,然后把获取到的DOM添加到实例身上。     * 3、如果是数组或许伪数组,那么把每一项分别添加到实例身上。     * 4、除了上面的数据类型,剩余的,统一添加到实例身上。     * */    // 判断是不是html片段    init.isHTML = function (html) {        // 如果是空类型的,直接返回false        if (!html) {            return false;        }        // 如果字符串的第一个字母是<,最后一个字母是>,并且length >= 3,就可以认为是html片段。        if (html.charAt(0) == '<' && html.charAt(html.length - 1) == '>' && html.length >= 3) {            return true;        }        return false;    };    // 去掉字符串首尾空白字符    init.trim = function (str) {        // 不是字符串就不处理了        if (typeof str !== 'string') {            return str;        }        // 优先使用内置的trim方法        if (str.trim) {            return str.trim();        }        // 把首尾空白字符替换为空,然后返回        return str.replace(/^\s+|\s+$/g, '');    };    // 判断是不是函数    init.isFunction = function (fn) {        if (typeof fn == 'function') {            return true;        }        return false;    },        // 判断是不是window            init.isWindow = function (w) {                if (w.window == w) {                    return true;                }                return false;            },        // 判断是不是伪数组或真数组        init.isLikeArray = function( arr ) {            // 过滤函数和window,以及非对象的其他数据            if ( init.isFunction( arr ) || init.isWindow( arr ) || typeof arr !== 'object' ) {                return false;            }            // 判断是不是真数组            if ( ({}).toString.call( arr ) == '[object Array]' ) {                return true;            }            // 判断是不是伪数组            // arr必须有length,在这个基础上,要么length为0,要么有length - 1这个属性值            if ( ('length' in arr) && ( (arr.length === 0) || (arr.length - 1 in arr) ) ) {                return true;            }            return false;        };    function init(selector) {        // 传入null、undefined、0、NaN、''返回空对象( 即空实例 )        if (!selector) {            return this;        }        // 传入字符串,那么需要判断是html片段 还是 其它        else if (typeof selector == 'string') {            // 为了用户友好体验,先去掉首尾空白字符            selector = init.trim(selector);            // 如果是片段,则创建对应的DOM,然后添加到实例身上,            // 如果字符串的第一个字母是<,最后一个字母是>,并且length >= 3,就可以认为是html片段。            if (init.isHTML(selector)) {                /*                 * 创建的思路:                 * 1、先创建一个临时的div容器                 * 2、设置这个div的innerHTML为html片段,                 * 这些片段就自动转变为了div的子元素,                 * 3、然后遍历div的子元素分别添加this身上,记住给实例补充length属性值,                 *  可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。                 * */                var tempDiv = document.createElement('div');                tempDiv.innerHTML = selector;                [].push.apply(this, tempDiv.childNodes);                return this;            }            // 否则按照选择器获取页面中的DOM,然后把获取到的DOM添加到实例身上            else {                /*                 * 实现的思路:                 * 1、使用querySelectorAll获取页面中的元素                 * 2、然后遍历获取到所有元素分别添加this身上,记住给实例补充length属性值,                 * 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。                 * */                try {                    var nodes = document.querySelectorAll(selector);                    [].push.apply(this, nodes);                    return this;                } catch (e) {                    this.length = 0;                    return this;                }            }        }        /*         * 判断是不是真假数组的思路:         * 1、先把函数和window排除掉,         * 2、然后通过toString来判断是不是真数组         * 3、否则再判断是不是伪数组         * 备注:下面的判断只用来判断是不是伪数组,不要用下面的判断条件判断真数组,         *       例如:[ 0:1, , , ] 使用下面的判断,就会得到false,造成真数组的误判。         * 3.1、 先看看这个对象有没有length属性,         * 3.2、 如果有,看看length的值是不是为0,如果为0,OK是伪数组,         * 3.3、 如果length的值不为0,看看这个数据有没有 length - 1这个属性,如果有,OK是伪数组。         * 建议把这个是否是真假数组的判断封装为一个函数,在这里调用。         * */        else if (init.isLikeArray(selector)) {            /*             * 实现的思路:             * 把真或伪数组中的每一项分别添加到实例身上,记住给实例补充length属性值,             * 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。             * */            [].push.apply(this, selector);        }        else {            /*             * 实现的思路:             * 把这个参数直接添加到实例身上,length为1即可。             * */            this[0] = selector;            this.length = 1;        }    }    //---------------以下为测试部分------------------    // 测试html片段    /*var $spans = new init('<span>123</span>放松地放量加速离开的<span>321</span>');     console.log( $spans );     var $divs = new init('<div><span>sdsfsdfs</span><span>dgdfgdf</span></div>');     document.body.appendChild( $spans[0] );     document.body.appendChild( $divs[0] );*/    // 测试选择器---    /*var $as = new init('a');     console.log( $as );     document.body.appendChild( $as[0] );     var $spans = new init('span');     console.log( $spans );     var $$ = new init('##dsfsd**');     console.log( $$ );*/    //        var a = new init([1,2,3]);    //        console.log(a);    var a = new init([1,2,3,4]);    console.log(a);    //    //        console.log(init.isLikeArray([1, ,3]));    //        console.log(init.isLikeArray({length: 0}));    //        console.log(init.isLikeArray({length: 3, 0: 1, 1: 2, 2: 3}));    //        console.log(init.isLikeArray({length: 10, 9: 999}));    //    //    //        console.log(init.isLikeArray({0: 1, 1: 2, 2: 3}));    //        console.log(init.isLikeArray({length:5}));    //        console.log(init.isLikeArray({length:5, 0: 1, 1: 2, 2: 3}));</script></body></html>