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

87 篇文章 0 订阅
10 篇文章 0 订阅

通过$工厂,最终到达了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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值