jQuery的一些简单知识点(一)

本文深入探讨JavaScript中对象和数组的基本概念,包括如何利用Object.prototype.toString方法辨别不同类型的对象,解析代码块与对象的区别,以及揭示toString方法在不同类型中的应用。此外,还详细介绍了jQuery的工作原理及其插件机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.必备tips1:Object.prototype.toString

    /*
     * Object.prototype.toString
     * 作用:根据内部的this返回一个类似于这样的字符串'[object constructorName]'
     * 这个方法有个缺点,不能获取用户自定义对象的具体类型,只能获取内置对象的类型。
     * */

    console.log(typeof []);//object
    console.log([]);//根据打印找constructorName
    console.log(Object.prototype.toString.call([]));//[object Array]

    console.log(typeof new Date());//object
    console.log(Object.prototype.toString.call(new Date()));//[object Date]

    console.log(typeof Array);//function
    console.log(Array); //ƒ Array() { [native code] }
    console.log(Object.prototype.toString.call(Array));//[object Function]

    console.log(typeof Date);//function
    console.log(Object.prototype.toString.call(Date));//[object Function]

    // 简写 ==> 因为{}对象直接继承Object.prototype,
    // 所以通过这个对象得到的toString,一定来自Object.prototype。
    //这里注意到{}外面加了一个小括号(),我们接下来会讲到,请往下看。
    console.log(({}).toString.call([]));//[object Array]
    console.log(({}).toString.call(new Date()));//[object Date]
    console.log(({}).toString.call(Array));//[object Function]
    console.log(({}).toString.call(Date));//[object Function]

    // 用这个toString获取自定义对象的类型
    //这个方法有个缺点,不能获取用户自定义对象的具体类型,只能获取内置对象的类型。
    function Person() {}
    var xiaofang = new Person();
    console.log(({}).toString.call(xiaofang)); //[object Object]

2.必备tips2:{ }代码块 和 对象

        /*
        * 什么是代码块:
        * 代码块就是一对大括号。
        *
        * 如果把一对大括号:
        1.赋值给其他变量,例如:var myobj={},
        2.或者参与运算,那么大括号就变成了字面对象,例如:用小括号包起来({})。
        * */
        var obj={};
        console.log(obj);//看控制台打印,并展开观察原型中的方法,toString是其原型中的方法


        {
            var a = 1;
            console.log(a);
        }
        console.log(typeof ({}));
        console.log(typeof {});
        // 需要通过运算,把{}转换为字面量,才能调用方法
        console.log(({}).toString()); // '[object Object]'
        console.log(obj.toString()); // '[object Object]'

        // 错误,代码块不能调用方法
        ({}).toString();
        // {}.toString(); 这样打开会报错

3.必备tips3:toString方法


    <script>

        // 字符串 ==> String.prototype.toString
        var a="ddd";
        console.log(a.toString());//ddd
        var e= new String();
        console.log(e.toString());//
        var e= new String('string');
        console.log(e.toString());//string

        // 数组 ==> Array.prototype.toString
        var b=[1,2,3,4,5,6];
        console.log(b.toString());//1,2,3,4,5,6
        var b=[];
        console.log(b.toString());//
        var d=new Array();
        console.log(d.toString());//

        // 对象  ==> Object.prototype.toString
        var c={};
        console.log(c.toString());//[object Object]

        // 函数 ==> Function.prototype.toString
        console.log(Function.toString());//function Function() { [native code] }
        console.log(Array.toString());//function Array() { [native code] }
        console.log(RegExp.toString());//function RegExp() { [native code] }
        function fn() {
            console.log('我写的');
        }
        console.log(fn.toString());
        // function fn() {
        //     console.log('我写的');
        // }
    </script>

4.jQuery的本质


<body>
    <script>
    // 真数组
    var arr = [1, 2, 3];
    console.log(arr);
    console.log(({}).toString.call(arr));//[object Array]
    console.log(arr.__proto__.constructor);//真数组的构造函数为"ƒ Array() { [native code] }函数"

    /*
     * jquery对外暴露了两个方法:jQuery和$,
     * 这两方法实际上是同一个方法,
     * 通过调用这两个方法,可以得到一个jQuery实例对象。
     *
     * jQuery实例对象是一个伪数组对象。
     *
     * jQuery和$实际上是一个工厂函数。
     * */

    // 工厂函数直接调用,就可以得到一个实例

    var $div = $('<div></div>');
    var jQueryDiv = jQuery('<div></div>');

    console.log($div);
    console.log($div.__proto__.constructor);//伪数组的构造函数不是"ƒ Array() { [native code] }函数"

    console.log(jQueryDiv);
    console.log(jQueryDiv.__proto__.constructor);


    // 验证实例是伪装组
    console.log(({}).toString.call($div));//[object Object]
    </script>

4.真数组伪数组PK

    <script>
        /*
        * 数组的分类:
        *
        * 1、真数组
        * new Array 创建的数组,或者字面量形式 [] 创建的数组,都是真数组。
        * 1.1 稀疏数组
        * 数组中,某些下标不存在,即为稀疏数组。
        * 1.2 非稀疏数组
        * 数组中没有缺失任何值。
        *
        * 2、伪数组
        * 必须要有length属性,
        * 要么length为0,要么有length - 1为下标的属性。
        * */

        /*
        * 伪数组的特点:
        * 1、必须要有length属性
        * 2、如果length属性值为0,那么这个对象有没有元素无所谓
        * 3、如果length属性值不为0,那么这个对象一定有 (length - 1) 为下标的属性值。
        * */

        // 是伪装组
        var obj = { length: 0 };
        var obj = { length: 4, 3: 'a' }; // 没有0,1,2可以认为0,1,2存的是undefined
        var obj = { length: 2, 0: 'a', 1: 'b' };

        // 不是伪数组,因为没有 9(length - 1) 这个属性
        var obj = { length: 10, 0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f' };
    </script>

5.jQuery插件机制

    <script>
        /*
        * jQuery插件实现机制:
        * 就是给原型添加一些功能方法。
        * */

        // 咱们的自调结构,沿用了1.7的版本
        (function( w ) {

            // 对外暴露的工厂函数
            function jQuery() {
                return new jQuery.fn.init();
            }

            // 给原型提供一个简写方式
            jQuery.fn = jQuery.prototype = {

            };

            // init是jQuery中真正的构造函数
            var init = jQuery.fn.init = function() {

            };

            // 替换构造函数的原型 为 jQuery工厂的原型
            //为了实现插件机制,让外界可以透过jQuery.fn扩充方法。
            init.prototype = jQuery.fn;

            // 把工厂通过两个变量暴露出去
            w.jQuery = w.$ = jQuery;

        }( window ));

        // 实现一个jQ弹出框插件
        jQuery.fn.alert = function( msg ) {
            alert( msg );
        };

        // 测试插件
        var $$ = $();
        $$.alert('弹出框插件');
    </script>

6.jQuery入口函数的实现思路


    <script>

        /*
        * jQ入口函数根据不同参数创建实例的样式,入口函数的参数无非以下几种:
        *
        * 测试用例:
        * 1、传入null、undefined、0、NaN、''
        * 2、选择器
        * 3、html片段
        * 4、数组
        * 5、伪数组
        * 6、对象
        * 7、其他基本数据类型
        * 8、DOM
        * */

简化版:
        function init(selector){
            if (!selector) {
                //1、传入null、undefined、0、NaN、''返回空对象( 即空实例 )
                return this;
            }else if(typeof selector == 'string'){
                if () {
                    //2、传入字符串,那么需要判断是HTML片段,如果是片段,则创建对应的DOM,然后添加到实例身上  $('<span>hello world</span>')
                }else{
                    //否则按照选择器获取页面中的DOM,然后把获取到的DOM添加到实例身上。
                    //DOM元素 $('.test') $('#test') $('div') 
                }

            }else if (){
                //3、如果是数组或伪数组,那么把每一项分别添加到实例身上。
            }else{
                //4、除了上面的数据类型,剩余的,统一添加到实例身上。
            }
        }

细化版(简化版的细化版):
        function init( selector ) {

            // 传入null、undefined、0、NaN、''返回空对象( 即空实例 )
            if ( !selector ) {
                return this;
            }

            // 传入字符串,那么需要判断是html片段 还是 其它
            else if ( typeof selector == 'string' ) {

                // 如果是片段,则创建对应的DOM,然后添加到实例身上,
                // 如果字符串的第一个字母是<,最后一个字母是>,并且length >= 3,就可以认为是html片段。
                if (  ) {

                    /*
                    * 创建的思路:
                    * 1、先创建一个临时的div容器
                    * 2、设置这个div的innerHTML为html片段,
                    * 这些片段就自动转变为了div的子元素,
                    * 3、然后遍历div的子元素分别添加this身上,记住给实例补充length属性值,
                    *  可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
                    * */

                }

                // 否则按照选择器获取页面中的DOM,然后把获取到的DOM添加到实例身上
                else {

                    /*
                    * 实现的思路:
                    * 1、使用querySelectorAll获取页面中的元素
                    * 2、然后遍历获取到所有元素分别添加this身上,记住给实例补充length属性值,
                    * 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
                    * */
                }

            }

            /*
            * 判断是不是真假数组的思路:
            * 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 (  ) {

                /*
                * 实现的思路:
                * 把真或伪数组中的每一项分别添加到实例身上,记住给实例补充length属性值,
                * 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
                * */
            }
            else {
                /*
                * 实现的思路:
                * 把这个参数直接添加到实例身子,length为1即可。
                * */
            }

        }
        console.log(new init(null));;
    </script>

7.细化版本中对字符串的处理

        function init(selector){
            if (!selector) {
                //1、传入null、undefined、0、NaN、''返回空对象( 即空实例 )
                return this;
            }else if(typeof selector == 'string'){
                if () {
                    //2、传入字符串,那么需要判断是HTML片段,如果是片段,则创建对应的DOM,然后添加到实例身上  $('<span>hello world</span>')
                }else{
                    //否则按照选择器获取页面中的DOM,然后把获取到的DOM添加到实例身上。
                    //DOM元素 $('.test') $('#test') $('div') 
                }

            }else if (){
                //3、如果是数组或伪数组,那么把每一项分别添加到实例身上。
            }else{
                //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, '');
    }

    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 (true) {

            /*
             * 实现的思路:
             * 把真或伪数组中的每一项分别添加到实例身上,记住给实例补充length属性值,
             * 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
             * */
        } else {
            /*
             * 实现的思路:
             * 把这个参数直接添加到实例身子,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]);

8.入口函数对各种类型的判断原理

    // 判断是不是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){
            if (init.isFunction(arr) || init.isWindow(arr) ||typeof arr!=='object') {
                return false;
            }
            if (({}).toString.call(arr) == '[object Array]') {
                return true;
            }
        }

        // 判断是不是伪数组或真数组
    init.isLikeArray = function(arr) {

            // 过滤函数和window,以及非对象的其他数据

            // 真数组(以下屏蔽的六行代码为)
            // var arr=[];
            // console.log(typeof arr);//object

            // // 伪数组
            // var obj ={length:0};
            // console.log(typeof obj);//object

            // console.log(({}).toString.call(arr));//[object Array]
            // console.log(({}).toString.call(obj));//[object Object]

            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 a = new init([1, 2, 3, 4]);
    console.log(a);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值