zoukankan      html  css  js  c++  java
  • 分析一个类似于jquery的小框架

    在网上下了一个类似于jQuery的小框架,分析源码,看看怎么写框架。

    选择器Select

    //用沙箱闭包其整个代码,只有itcast和I暴漏在全局作用域
    (function( window , undefined){
        //Itcast函数,参数:selector。返回值一个Itcast对象,功能:new Itcast。prototype。init()
        function Itcast(selector){
            return new Itcast.prototype.init();
        }
        // Itcast的原型属性用替换重新定义
        Itcast.prototype = {
            constructor: Itcast,
            type: "Itcast",
            length: 0,
            //constructor指向构造函数Itcast,type记录对象类型“Itcast”,length:变成伪数组
            // init函数 功能:Itcast对象的真正的构造函数,根据参数类型,进行不同的处理: 参数:selector。
            // 返回值:只要在适当的位置返回即可,构造函数不需要返回值,但是为了提醒这里是为了创建对象,所以写成return this
            //因为init是构造函数,this就是指创建出来的这个对象,现在要把获取到的dom对象全部追加到this中来,再通过Itcast返回
            // 。因为Itcast和init是用的同一个原型,所以认为此处创建出来的就是Itcast对象
            init:function(selector){
                var push = [].push;
                if( typeof selector == "string"){
                    // 如果selector是html字符串,用parseHtml将其转成DOM伪数组,再转成this(Itcast伪数组)
                    if( selector.charAt(0) == "<"){
                        push.apply(this , parseHTML(selector));
                    }else{
                        // 如果selector是选择器。用Select函数,
                        push.apply(this , Select(selector));
                    }
    
                }
                //   如果是function ,近似于onload
                if( typeof selector == "function"){
    
                }
                //  如果是dom,追加到this(Itcast伪数组)中
                if( selector.nodeType ){
    
                }
                // 如果是Itcast对象,追加到新的Itcast对象中返回
                if( selector.type = "Itcast" ){
    
                }
            }
        }
    
        //让init的原型属性指向Itcast。prototype。即有init创建出来的对象也就是Itcast对象了
        Itcast.prototype.init.prototype = Itcast.fn = Itcast.prototype;
        //设定Itcast的扩展方式,Itcast。extend(静态成员扩展) 。 Itcast.prototype.extend(动态成员扩展)
        // .函数参数: 对象option。 返回值: 无, 功能:将option中的属性或方法依次添加给Itcast或Itcast.fn
        Itcast.fn.extend = Itcast.extend = function(option){
            for( var k in option){
                this[ k ]  = option[ k ];
            }
        }
        //模块化,功能化。(构造函数的补充)
            //扩充静态成员
                //选择器Select(闭包,仅将Select暴漏在外面)参数:无,返回值Select函数。
                // 功能:再沙箱中将Select函数定义好,
        var Select = (function(){
            //数据初始化:
            //将某些浏览器是否支持a方法用对象support储存起来以免每一次动用函数的时候都要进行查找
            // 是否提供可以看函数体是否包含 [native code]即可;,正则表达式的变量以r开头
            var rnative = /[native code]/,
                push = [].push ,
                i,
                div = document.createElement("div");
            var support = {
                qsa: rnative.test(document.querySelectorAll),
                getByClass : rnative.test( document.getElementsByClassName),
                getByClass2: rnative.test(div.getElementsByClassName),
                trim: rnative.test(String.prototype.trim),
                indexOf: rnative.test(Array.prototype.indexOf),
            }
            // 要用的函数提前准备好
            // push,push没有兼容性问题但是push.apply再IE低版本,不能展开伪数组,会报错
            // ,因此用try{}catch的方法兼容
            try{
                push.apply([],document.getElementsByTagName("*"));
            }catch(e){
                //z自定义push.apply的函数,参数数组a,伪数组b, 返回值 数组a,
                // 功能:将b中的内容添加到 a当中;
                var  push = {
                    apply : function( a , b){
                        for( var i =0 ; i< b.length ; i++ ){
                            a[ a.length++ ] = b[ i ];
                        }
                        return a;
                    }
                }
            }
            //trim 参数:字符串 ,返回值:首位去除空白的I字符串。功能:将字符串的两端的空白去出,并返回
            function trim( str ){
                if( support.trim ){
                    return str.trim();
                }else{
                    var rtrim = /^s+|s+$/;
                    return  str.replace( rtrim , "");
                }
            }
            // indexOf,参数数组arr,a要查找项,返回值:a的索引值,如果没有返回-1
            //indexOf 还需要一个参数, 就是 查找的开始位置
            function indexOf( arr , a,startIndex){
                startIndex = startIndex || 0;
                if(support.indexOf){
                    return arr.indexOf(a , startIndex);
                }
                for(var i = startIndex; i< arr.length ;i++){
                    if( arr[ i ] === a){
                        return i;
                    }
                }
                return -1;
            }
            //unique函数,参数:数组 ,返回值:去重之后的数组,功能: 将穿进来的数组中的重复项去除
            function unique( arr ){
                var array = [];
                for( var i=0 ; i< arr.length ;i++){
                    if(indexOf( array ,arr[ i ]) == -1){
                        array.push( arr[i]);
                    }
                }
                return array;
            }
            //核心函数Select:参数:selector选择器, 要被添加元素的数组或伪数组results, 返回值results
            //功能: 将selector对应的DOM对象,追加到results中输出
            function Select(selector ,results){
                results = results || [];
                if( typeof selector !== "string"){
                    return ;
                }
                //如果浏览器支持querySelectorAll就用,如果不支持,就自己定义一个select2
                if( support.qsa ){
                    return document.querySelectorAll( selector );
                }else {
                    return select2( selector);
                }
            }
            // select2,参数:selector选择器,返回值dom对象,
            function select2( selector ,results){
                // 功能:看选择器是不是并集选择器,将selector用trim函数去掉首尾的空白()
                results = results || [];
                // ,再用split函数切割成数组,
                var arr = selector.split(",");
                for( i = 0 ; i < arr.length ; i++){
                // 再用select3函数进行处理,将切割好的字符串用trim方法取出前后空白
                 select3( trim(arr[ i ]) , results);
                }
                return unique(results);
            }
            function select3 ( selector , results){
                results = results || [];
                //select3函数:参数select ,返回值dom对象。功能:判断选择器是“*”还是id,还是类,还是标签
                var first = selector.charAt(0);
                //注意如果是类选择器,document.getElementsByClassName有浏览器兼容性问题。
                //区分好后,调用相应的函数进行处理
               //此处屏蔽掉后代选择器的影响,此时如果selector经过了首尾去空格后还有空格,说明是后代选择器
                if( selector.slice(" ").length == 1){
                    if(selector == "*"){
                        /*
                         results = document.getElementsByTagName("*");
                         return results;
                         ,如果results原来就有内容,此处把results中的内容全部覆盖了所以不行,
                         要将选择器对应的dom元素挨个追加到results中
                         */
                    }else if( first == "#"){
                        return id(selector.slice(1) , results);
                    }else if( first == "."){
                        //类
                        return c(selector.slice(1),results);
                    }else {
                        //标签
                        return t(selector , results)
                    }
                }else{
                    //如果是后代选择器,此处咱不处理,抛出一个bug,提示升级浏览器
                    throw new Error("您的浏览器版本过低,请升级浏览器")
                }
            }
    
            //参数:选择器selector 被追加元素的数组。 返回值: results
            //功能: 将selector对应的元素挨个追加到results中并输出,
            function id( selector ,results ){
                results = results || [];
                push.apply(results , document.getElementById(selector));
                return results;
            }
           // 标签
            function t( selector , results){
                results = results || [];
                push.apply( results , document.getElementsByTagName( selector));
                return results;
            }
            //类,getElementsByClassName有浏览器兼容行问题,
            function c( selector , results ){
                results = results || [];
                push.apply( results , getByClass( selector , document));
                return results;
            }
    
            //兼容类选择器,参数:类名className ,查找返回node,返回值:返回查找到的dom元素数组
            //功能: 用className属性查找node中的符合条件的dom对象,并返回对象数组
            function getByClass(className , node){
                node = node || document;
                //如果浏览器支持
                if( node == document && support.getByClass || node.nodeType && support.getByClass2){
                    return node.getElementsByClassName(className);
                }else{
                    //如果浏览器不支持
                    //获取所有的标签,遍历
                    var list = node.getElementsByTagName("*"),
                        arr = [],
                        tempClassName;
                    for( var i = 0 ; i< list.length ;i++){
                        tempClassName = list[ i ];
                        if( !tempClassName ){
                            continue;
                        }    //再class属性存在的情况下
                        //用slice(“ ”)分割
                        //判断是否与className相同
                        //如果相同追加到results中
                        if(indexOf(tempClassName.slice(" "),className) !== -1){
                            arr.push(tempClassName);
                        }
                    }
                    return arr;
    
                }
    
            }
    
            return Select;
        })();
    
    
    
                // 解析html字符串parseHTML
                    //在解析过程中,需要在内存中创建一个node,为了不暴漏在外面使用沙箱(自调自用的函数,返回该数组)
                    //参数:selector,(html字符串),返回值存储dom的数组,功能: 将html字符串转化成dom对象储存在数组中
        Itcast.parseHTML =(function (){
            var node = document.createElement("div");
            var arr = [];
            function parseHTML(selector){
                node.innerHTML = selector;
                arr.push.apply(arr , node.childNodes);
                return arr;
            }
            return parseHTML;
        })();
    
        //扩充实例成员
      Itcast.fn.extend({
          appendTo: function ( parent , child ){
              parent.appendChild( child );
          }
      })
    
    
    
        //将Itcast挂在window上
        window.Itcast = window.I = Itcast;
    })(window);
    

      

  • 相关阅读:
    java+phantomjs实现动态网页抓取
    windows 安装 cordova
    windows系统安装 ionic
    windows系统 安装 mysql.fx
    安装 Navicat for MySQL
    windows 安装 MySQL
    调用百度地图api隐藏版权信息
    ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
    Angular 调用百度地图API接口
    Angular 使用 frame 加载网络资源显示路径不安全问题
  • 原文地址:https://www.cnblogs.com/bridge7839/p/5797761.html
Copyright © 2011-2022 走看看