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

来源:互联网 发布:抓阄软件 编辑:程序博客网 时间:2024/05/21 10:10

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);