美文网首页Web
JS中JQ框架的分析

JS中JQ框架的分析

作者: 追逐_chase | 来源:发表于2019-09-18 14:13 被阅读0次
    web.jpeg

    1. 首先我们在看jQ代码的时候 发现整体是一个 闭包函数

    // JQ的整体是一个自调用函数/闭包
    (function(window,undefined){
    
    })(window)
    

    作用:
    1.防止全局变量污染(只提送2个变量 $ 和 jQuery)
    2.保护内部的代码不会被覆盖
    其中 里面的2个参数 windowundefined值默认不能被修改,但是在IE9-是可以被修改的

    • window不用多解释,全局的对对象

    2.JQ使用的事工厂函数

    
    //自调用函数
    (function(window,undefiend){
        
        //1.创建工厂函数
        var jQuery = function(select){
            //返回一个 构造函数
            return  new jQuery.fn.init(select);
        }
    
        
    
        //2. 设置元素对象和原型对象
        jQuery.fn = jQuery.prototype = {
            constructor:jQuery,
            //初始化方法 匿名的构造函数
            init:function(select){
            
            }
        }
    
        //3.更改init构造函数的原型对象 指向 jQuery.prototype
        jQuery.fn.init.prototype = jQuery.prototype;
    
    
        //4.给外界提供一个变量
        window.jQuery = window.$ = jQuery;
    
    
    })(window);
    
    

    3.jQ的参数分析

    1.如果条件判断为假 0 false null undefined NaN ... 返回空的jQ实例对象

      jQuery.fn = jQuery.prototype = {
            constructor:jQuery,
            init:function (selector) {
                //条件判断为假 返回空的jQ对象
                if(!selector)
                {
                   return this;
                }
            }
        }
    
    1. 字符串(标签) 返回所有标签保存到jQ实例对象 比如$("<span>我是spanA</span><span>我是spanB</span>")
     jQuery.fn = jQuery.prototype = {
            constructor:jQuery,
            init:function (selector) {
                //[1] 条件判断为假 返回空的jQ对象
                if(!selector)
                {
                   return this;
                }
    
                //[2] 参数是字符串
                else if(Tool.isString(selector))
                {
                    //参数是标签
                    //<div></div>
                    //总结判断的条件:必须以<开头 && 必须以>结尾 && 长度>=3
                    //charAt(index) 获取字符串中指定的字符  "zhangsan"
                    //容错性处理:包容用户
                    selector = Tool.trim(selector);
                    if(Tool.isHTML(selector))
                    {
                        //console.log("参数是标签");
                        //console.log(typeof selector);
                        //把参数中所有的一级标签都保存到jQ实例对象中返回
                        //分析: 创建一个临时的div 存储标签字符串
                        //     把所有获取的标签都存到当前jQ实例对象中(this)
                        //     更新length的值
                        var tempEle = document.createElement("div");
                        tempEle.innerHTML = selector;
                        var nodes = tempEle.children;
                        //console.log(tempEle);
                        //console.log(nodes);
                        for(var i = 0;i<nodes.length;i++)
                        {
                            this[i] = nodes[i];
                        }
                        //console.log("this",this);
                        this.length = nodes.length;
                        return this;
                    }
                    //参数是选择器
                    else
                    {
                        console.log("其他情况");
                    }
                }
    
                // 数组
            }
        }
    
    //工具方法
     var Tool = {
            isString:function (str) {
            return typeof str === "string"
        },
            isHTML:function (html) {
            return html.charAt(0) === "<" && html.charAt(html.length -1) ===">" && html.length >=3
        },
            trim:function (text) {
            //检测当前环境是否支持trim方法,如果支持那么就直接使用
            if(text.trim)
            {
                return text.trim();
            }else
            {
           
                return text.replace(/^\s+|\s+$/g,"")
            }
        }
        }
    
    1. 字符串(选择器)把参数中所有的一级标签都保存到jQ实例对象中返回
      比如:
    //获取参数
     var nodes = document.querySelectorAll(selector);
    //遍历 查看是否有自标签
          for(var i = 0;i<nodes.length;i++){
                            this[i] = nodes[i];
                 }
          this.length = nodes.length;
    
    //获取使用  call / apply借调函数
    
     [].push.apply(this,document.querySelectorAll(selector));
    
    

    4.数组 |伪数组(本质是对象) 返回jQ实例对象

       [].push.apply(this,selector);
        return this;  //返回jQ对象
    

    5.如果参数是函数,那么会监听DOM的加载,等DOM加载完执行回调函数中的代码

    
    //闭包函数
    (function(window,undefined){
        //1.创建工厂函数
        var jQuery = function(select){
            
            return  new jQuery.fn.init(select);
        };
    
        //2.设置原型对象
        jQuery.fn = jQuery.prototype = {
            constructor:jQuery,
            init:function(select){
                //1.判断条件是否为假
                if(!select){
    
                    return this;
                } else if(tool.isFunction(select)){
                    this.ready(selector);
                }
                 //2.判断字符串
                  //console.log(typeof selector);
                        //把参数中所有的一级标签都保存到jQ实例对象中返回
                        //分析:(001)需要根据字符串获取一级标签
                        //     (002)把所有获取的标签都存到当前jQ实例对象中(this)
                        //     (003)更新length的值
                else if(tool.isString(select)){
                    //取出空格
                    select = tool.trim(select);
                    //匹配标签字符串
                    if(tool.isHTML(select)){
                        //创建一个临时div 包裹
                        var tempElement = document.createElement("div");
                        //把标签字符串设置 div的内容 获取div的 子元素
                        tempElement.innerHTML = select;
    
                        var nodes = tempElement.children;
    
                        for(var i =0 ; i < nodes.length; i ++){
                            //包装成 JQ对象  this就是创建JQ的对象
                            this[i] = nodes[i];
                        }
    
                        this.length = nodes.length;
    
                        return this;
    
                    }
                    //字符串是选择器
                    else{
    
                         //(001) 根据参数获取所有指定的标签
                        //(002) 把所有获取的标签存储到jQ实例对象中返回
                        //(003) 更新length的值,返回jQ实例对象
                        //"div"
                        //#demoID
                        //.box
    
                        // var nodes = document.querySelectorAll(select);
                        // for(var i = 0; i < nodes.length; i ++){
                        //     this[i] = nodes[i];
                        // }
                        // this.length = nodes.length;
    
                        // apply借调函数的使用
                        // this借调数组[] push的方法
                        // push是  Array.prototype.push 的原型方法
                        //这个方法 等价于 上面的for 遍历
                        [].push.apply(this,document.querySelectorAll(select));
    
                        return this;
    
                    }
    
                }
                //3.判断是否为 数组/为数组
                else if(tool.isArray(select) || tool.isLikeArray(select)){
    
                   //IE8之前调用下面的方法会报错
                   //select是伪数组的时候
                   //处理,把为数组转化为数组
                   var arrt = [].slice.call(select);
                    [].push.apply(this,arrt);
    
                    return this;
                }
                //其他参数
                else{
                    this[0] = select;
                    this.length = 1;
                }
                
            },
            ready:function(fn){
                //判断是不是已经加载完成了,如果是 直接调用
                if(document.readyState == "complete") {
                    fn();
                    return;
                }
                //不是
                //监听DOM 加载完成 
                if(document.addEventListener){
                    document.addEventListener("DOMContentLoaded",fn);
                } else{
                    //兼容IE的方法
                    document.attachEvent("onreadystatechange",function(){
                        if(document.readyState == "complete") {
                            fn();
                          
                        }
                    });
    
                }
            }
        }
    
       //抽出的工具方法
       var tool = {
           isObject:function(obj){
            return typeof obj == "object" && obj != null;
           },
           isWindow(obj){
            return obj === window.window;
           },
           isString:function(str){
                return (typeof str === "string");
           },
           isHTML:function(html){
               //判断是字符串是否是标签 <h1>zheshi</h1>
            return  html.chatAt(0) === "<" && html.chatAt(html.lenth -1) === ">"&&html.length >= 3;
           },
           trim:function(text){
               //判断是否支持这个方法
               if(text.trim){
    
                return text.trim();
    
               } else{
                //处理字符串中的空格
                // 把空格替换掉
                return text.replace(/^\s+|\s+$/g,"");
               }
           },
           isArray:function(arr){
               //处理是不是数组
               if(Array.isArray){
                   //ES5
                   return Array.isArray(arr);
               } else{
                    //ES5之前的
                return Object.prototype.toString.call(arr) === "[object Array]";
               }
           },
           /**
            * (1) 是对象
            * (2) 拥有length属性
            * (3) 拥有length-1属性
            * (4) 不是window
            */
           isLikeArray:function(likeArray){
            return this.isObject && length in likeArray && likeArray.length - 1 in likeArray && !tool.isWindow(likeArray);
           },
           isFunction:function(fn){
                return typeof fn == "function";
           }
       };
    
        //3.更改init的构造函数的原型对象的指向
        jQuery.fn.init.prototype = jQuery.prototype;
    
         jQuery.tool = tool;
    
        //4.提供全局变量给外部
        window.jQuery = window.$ = jQuery;
        
    
    
    })(window);
    

    4.工具优化---插件机制

    我们知道jQ提供的2个参数分别是$jQuery,那么如何暴露给外面一些工具方法,或者是对象方法呢?

    答案是:原型对象

      //优化工具方法
        jQuery.fn.extend = jQuery.extend = function(obj){
            for(var i in obj){
                this[i] = obj[i];
            }
    }
    
    

    jQuery.fn.extend 其实就是 jQuery.prototype..extend 给原型对象扩展方法

    jQuery.extend 扩展其实就是 jQuery = function(){}函数,扩展静态的属性或者方法

    比如:

     // 工厂函数 添加属性或者方法
        jQuery.extend({
            isObject:function(obj){
    
                return typeof obj == "object" && obj != null;
            },
            isWindow:function(obj){
                
                return obj === window.window;
            },
            isString:function(str){
    
                return (typeof str == "string");
            },
            isHtml:function(html){
                return html.charAt(0) === "<" && html.charAt(html.length -1) === ">" && html.length >= 3;
            },
            trim:function(text){
                if(text.trim){
                   return text.trim(); 
                }else {
                    //排除空格
                    return text.replace(/^\s+|^s+$/g,"");
                }
            },
            isArray:function(tempArr){
                if(Array.isArray){
                    return Array.isArray(tempArr);
                }else{
                    //es5之前 调用object的原型对象tostring 处理
                    return Object.prototype.toString.call(tempArr) == "[object Array]";
                }
            },
            isLikeArray:function(tempArr){
                return this.isObject && length in tempArr && tempArr.length - 1 in tempArr && !this.isWindow(tempArr);
            },
            isFunction:function(fn){
    
                return  typeof fn == "function";
            }
    
        });
        
     
    
    jQ的所谓插件机制就是这样给或者实例对象来扩充自己的方法

    相关文章

      网友评论

        本文标题:JS中JQ框架的分析

        本文链接:https://www.haomeiwen.com/subject/fqmgyctx.html