• 深入理解jQuery框架-框架结构


     这是本人结合资料视频总结出来的jQuery大体框架结构,如果大家都熟悉了之后,相信你们也会写出看似高档的js框架;

     jquery框架的总体结构

    (function(w, undefined){
        //定义一些变量和函数   
        var
        //对外提供的接口
        jQuery = function( selector, context ) {
            return new jQuery.fn.init( selector, context, rootjQuery );
        };
    
        //结jQuery对象添加一些方法和属性
    
        //jQuery的继承方法
    
        //jQuery.extend 扩展一些工具的方法(静态方法) jQuery.trim();
    
        //Sizzle 复杂选择器的实现
    
        //Callbacks 回调对象--函数的统一管理
    
        //Deferred 延迟对象,对异步的统一管理
    
        //support 功能检测
    
        //Data 数据缓存     
    
        //queue 队列管理
    
        //Attribute 属性操作
    
        //Event 事件处理
    
        //DOM操作 添加删除、包装筛选等
    
        //CSS操作
    
        //提交的数据和ajax
    
        //运动/动画 FX
    
        //坐标和大小
    
        //支持的模块化的模式
        
        w.jQuery = w.$ = jQuery;
        
    })(window);

    jquery为什么要使用匿名函数来封装框架

     阅读jquery源码,我们可以看出jquery使用的是匿名函数来封装框架,那么为什么要使用这种方式呢,又有什么好处?

    1.什么是匿名函数?

    // 匿名函数的写法
    function(){
        console.log("test");    
    }
    
    // 将变量赋值给一个匿名函数
    var test = function(){
        return 0;
    }
    console.log(test);    //打印的是变量test,即函数
    console.log(test()); //打印0,test + ()表示调用这个方法

    2.匿名函数自调用的方式

    匿名函数有两种调用方式,第一种是()()、第二种是 (())

    // ()()调用方式
    (function(){ console.log("匿名函数-自调用方法1"); })();
    // (())调用方式 (
    function(){ console.log("匿名函数-自调用方法2"); }());

    3.匿名函数传参

    /*错误方式*/
    (function(window){
        console.log(window);    //undefined    
    })();
    
    /*正确方式*/
    var jQuery;
    (function(win, jQuery){
        console.log(win);    //
    })(window, jQuery);

    4.使用匿名函数对外提供一个接口

    (function(w) {
        var Person = function() {
            this.name = "cxb";
            this.talk = function() {
                console.log("hello, I'm " + this.name);    
            }
        }
        
        w.Person = Person;
    })(window)
    
    var p = new Person();
    console.log(p.name);
    p.talk();

    5.使用匿名函数的好处:

    防止变量方法冲突 变量与方法是独立的,写在匿名函数的变量或函数属于局部的,不会受外面的干扰,也不会影响全局变量

    (function(){
        var a = 10;
        
        var fun = function() {
            console.log("fun method");    
        }
    })();
    console.log(a);           //报错 undefined
    fun();                    //报错 fun is not a function

     为什么可以直接使用jQuery 或 $为调用jquery方法?

    对象创建的比较

    创建对象方式一:

    function Student() {
        this.name = "cxb";
        this.talk = function() {
            return "我叫" + this.name;
        }
    }
    var stu1 = new Student();
    var stu2 = new Student();

    创建对象方式二:

    function Student() {
        this.name = "cxb";
    }
    Student.prototype.talk = function() {
        return "我叫" + this.name;
    }
    var stu1 = new Student();
    var stu2 = new Student();

    方式一与方式二产生的结构几乎是一样的,而本质区别就是:方式二new产生的二个实例对象共享了原型的talk方法,这样的好处节省了内存空间,方式一则是要为每一个实例复制talk方法,每个方法属性都占用一定的内存的空间,所以如果把所有属性方法都声明在构造函数中,就会无形的增大很多开销,这些实例化的对象的属性一模一样,都是对this的引用来处理。除此之外方式一的所有方法都是拷贝到当前实例对象上。方式二则是要通过scope连接到原型链上查找,这样就无形之中要多一层作用域链的查找了。

    所以说在jQuery中,可以看到很多 jQuery.fn 这样的写法(事实上在jQuery中,使用jQuery.fn替换了jQuery.prototype)。


    浅拷贝与深拷贝

    1. js对象的浅拷贝

    var a = [1,2,3];
    var b = a;
    var c = {name:"cxb", age:26};
    var d = c;
    console.log(a);
    console.log(b);
    console.log(c);
    console.log(d);

    [1, 2, 3]
    [1, 2, 3]
    Object {name: "cxb", age: 26}
    Object {name: "cxb", age: 26}

    b[2] = 5;
    d.age = 20;
    console.log(a);
    console.log(b);
    console.log(c);
    console.log(d);

    [1, 2, 5]
    [1, 2, 5]
    Object {name: "cxb", age: 20}
    Object {name: "cxb", age: 20}

    2.js数组的深拷贝

    var arr1 = [1, 2, 3];
    var arr2 = [];
    
    function deepCopy(arr1, arr2) {
       for(var i=0; i<arr1.length; i++) {
           arr2[i] = arr1[i];
       }
    }
    deepCopy(arr1, arr2);
    console.log(arr1);
    console.log(arr2);    
    arr2[2] = 5;
    console.log(arr1);
    console.log(arr2);

    [1, 2, 3]
    [1, 2, 3]
    [1, 2, 3]
    [1, 2, 5]

    3.js对象的深拷贝

    function Parent() {
        this.name = "李四";
        this.age = 40;
        this.talk = function() {
            console.log("hello, I'm "+ this.name);    
        }    
    }
    
    function Child() {
        this.name = "张三";
        this.age = 20;
        this.sound = function() {
            console.log("haha");    
        }        
    }
    Child.prototype = new Parent();
    var child = new Child();
    for(var key in child) {
        console.log(key);    
    }

    4.hasOwnProperty来过滤原型链上的属性

    for(var key in child) {
        if(child.hasOwnProperty(key))
        console.log(key);    
    }

    5.完整clone一个对象的方法

    var child = new Child();
    var childObject = {};
    for(var key in child) {
        if(child.hasOwnProperty(key))
        childObject[key] = child[key];    
    }
    console.log(childObject.name);
    console.log(childObject.age);
    childObject.sound();
    childObject.talk();

    jQuery框架的实现原理

    /******************** jQuery 框架部分 ************************/
    (function(w, undefined){
    //第一步:创建一个jQuery函数
    var jQuery = function() {
        //第四步:
        return new jQuery.fn.init();    
    }
    
    //第三步:
    jQuery.fn = jQuery.prototype;    //是覆盖prototype
    
    jQuery.fn = {
        //当创建了一个函数之后,js源码会自动生成 jQuery.prototype.constructor = jQuery;
        //在jQuery中使用这个是为了防止恶意修改:如 jQuery.prototype.constructor = Array;
        constructor : jQuery,
        
        init : function() {
            return this;
        },
    };
    jQuery.fn.init.prototype = jQuery.fn;    //如果不使用这个,在第四步当中是无法使用new的
    
    //第五步:使用extend将jQuery模块化(其实原码并不是这样的)这里使用了拷贝,关于拷贝请看 4.js浅拷贝与深拷贝
    //好处:插件扩展时直接使用此方法
    jQuery.fn.extend = jQuery.extend = function( ) {                                                                                                                                                                     var target = this, source = arguments[0] || { } ;
        for(var key in source) {
            if(source.hasOwnProperty(key)) {
                jQuery.fn[key] = jQuery[key] = source[key];    
            }
        }
        return target;
    }
    
    
    //第六步:模块一
    jQuery.fn.extend({
        
        html : function() {},    
        
        text : function() {},
        
    });
    
    //第六步:模块二
    jQuery.extend({
        
        ajax : function() {
            //处理json格式的参数及回调函数success,error
            console.log("ajax method");    
        },    
        
        each : function() {},
    });
    
    //第二步:对外提供一个接口
    w.jQuery = w.$ = jQuery;
    
        
    })(window);
    
    //测试1
    jQuery.ajax();
    
    
    //测试2:外部框架的扩展
    /******************** 基于jQuery框架的ui框架部分 ************************/
    (function(w, jQuery) {
        //jQuery对象的方法扩展
        jQuery.fn.extend({
            drag : function() {
                console.log("drag method");
            },
            
            dialog : function() {
                console.log("dialog method");
            },
        });
        //jQuery类的方法扩展
        jQuery.extend({
            tool : function() {
                console.log("tool method");
            },
            //....
        });
    })(window, jQuery);
    

     示例

    <html lang="zh-CN">
    <head>
    <script>
    (function(win, undefined){ var doc = win.document; var loc = win.location; var jQuery; jQuery = function(selector, context){ return new jQuery.fn.init(selector, context); } var _jQuery = win.jQuery, _$ = win.$; jQuery.fn = jQuery.prototype; jQuery.fn = { constructor: jQuery, init : function(selector, context){ if(selector.charAt(0)=="#"){ this.context = doc.getElementById(selector.substr(1)); }else if(selector.charAt(0)=="."){ this.context = doc.getElementsByName(selector.substr(1)); }else if(selector.charAt(0)==":"){ this.context = doc.getElementsByTagName(selector.substr(1)); }else{ this.context = doc.getElementsByTagName(selector); } return this; } } jQuery.fn.init.prototype = jQuery.fn; jQuery.fn.extend = jQuery.extend = function() { var target = this; var source = agruments[0] || { }; for (var p in source) { if (source.hasOwnProperty(p)) { target[p] = source[p]; } } return target; } // 对象的方法 jQuery.fn.extend( { val : function() { if((typeof _value)=="undefined"){ return this.context.value; }else if((typeof _value)=="string"){ return this.context.value=_value; } }, html : function() {}, text : function() {}, attr : function() {}, prop : function() {}, //... }); // CSS操作 jQuery.fn.extend( { addClass : function() {}, removeClass : function() {}, css : function() {}, //... }); // 插件扩展的方法 jQuery.extend( { ajax: function() {}, each: function() {}, when: function() {}, //... });
    // 对外提供的接口,即使用$ 或 jQuery win.jQuery
    = win.$ = jQuery; })(window); window.onload = function(){ var value = jQuery("#test").val(); console.log("------"+value); }
    </script>
    </head>

    <body>
    <input type="text" id="test" value="123456" />
    </body>
    </html>
  • 相关阅读:
    【u026】花园(garden)
    【BZOJ 1040】[ZJOI2008]骑士
    【t100】汤姆斯的天堂梦
    【BZOJ 1038】[ZJOI2008]瞭望塔
    【t096】树的序号
    Java Web整合开发(82)
    2 HTML解析
    T3186 队列练习2 codevs
    T3185 队列练习1 codevs
    T1191 数轴染色 codevs
  • 原文地址:https://www.cnblogs.com/caoxb/p/9376054.html
Copyright © 2020-2023  润新知