深入理解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>

复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值