zoukankan      html  css  js  c++  java
  • 深入理解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>
  • 相关阅读:
    公用表表达式(CTE)的递归调用
    c# 如何让tooltip显示文字换行
    实战 SQL Server 2008 数据库误删除数据的恢复
    SQL SERVER数据库中 是否可以对视图进行修改删除
    asp.net中实现文件批量上传
    sql server 2008学习2 文件和文件组
    sql server 2008学习3 表组织和索引组织
    sql server 2008学习4 设计索引的建议
    sql server 2008学习10 存储过程
    .net 调用 sql server 自定义函数,并输出返回值
  • 原文地址:https://www.cnblogs.com/caoxb/p/9376054.html
Copyright © 2011-2022 走看看