study icon indicating copy to clipboard operation
study copied to clipboard

jQuery概览

Open 24wangchen opened this issue 10 years ago • 0 comments

前言

作为一个前端工程师,jQuery肯定是个十分熟悉的工具,可以说是入门级框架。因此读懂jQuery并且理解其架构思想,对于一个初中级工程师来说,成长很大。jQuery经过这么多年的架构演变,版本也从1.x升级到了2.x,其中不乏很多设计精髓。它的API设计的很巧妙,使得很多新手可以不了解原生的JS条件下,完成一些常见的交互。前端很重要的一部分就是DOM操作,jQuery秉承其 The Write Less, Do More 的理念,将复杂的DOM操作封装出简单易用的API。 本文选择的版本是2.1.1

外层沙箱

沙箱是前端中很常见的一种方式。jQuery中,为了避免全局变量的污染,将代码放入一个自执行的函数中,然后暴露出命名空间。

(function( global, factory ){
    if( typeof module === "object" && typeof module.exports === "object" ){
        module.exports = global.document ? factory( global, true ) : function(){}
    }else{
        factory( global );
    }
}(window, function(){
    if( typeof noGlobal === strundefined ){
        window.jQuery = window.$ = jQuery;
    }
    return jQuery;
}))

jQuery的对象创建

jQuery没有使用正常的new来实例化出一个对象,而是调用其函数$(),真正实例化的是jQuery.fn.init函数

jQuery = function( selector, context ){
    return new jQuery.fn.init( selector, context );
}

那么问题来了,这个new出来的对象如何访问jQuery原型上的方法呢,关键在于这段代码

init = jQuery.fn.init = function(){}
init.prototype = jQuery.fn;

通过原型链的方式,将jQuery.fn全部挂载到了init的原型链中。(有关原型继承可参看原型继承) jQuery可调用的方法分为两种,一种是jQuery本身可调用的方法,即使用jQuery.extend扩展的;另外一种是生成的jQuery对象可以使用的方法,即使用jQuery.fn.extend扩展的。

扩展开发

jQuery对开发者提供了jQuery.fn.extend方法进行jQuery对象扩展。

jQuery.extend = jQuery.fn.extend = function(){
    var i = 1, length = arguments.length;
    if( i === length ){
        target = this;
        i--;
    }
}

通过target=this使得同一个函数实现了分别对jQuery自身和jQuery.fn的扩展

extend用法

extend( true, obj1, obj2, ... )//深层拷贝 extend( obj1, obj2 )//浅层拷贝 extend( obj )//自身对象的扩展 具体代码分析如下:

jQuery.extend = jQuery.fn.extend = function(){
    var options,//拷贝的对象
    name,//拷贝对象中的键名
    src,//被修改对象中的值
    copy,//拷贝对象的值
    copyIsArray,//是否是一个数组
    clone,//深层拷贝中被修改的对象
    target = arguments[0] || {},//被修改的对象
    i = 1,//默认开始遍历的起始索引值
    length = arguments.length,//参数长度
    deep = false;//默认浅层拷贝

    //处理深层拷贝的情况
    if( typeof target === "boolean" ){
        deep = target;
        target = arguments[i] || {};
        i++;
    }
    //处理被修改对象为字符串或其他非对象、函数类型的情况,初始化为空对象
    if( typeof target !== "object" && !jQuery.isFunction(target) ){
        target = {};
    }
    //扩展jQuery自身
    if( i === length ){
        target = this;
        i--;
    }
    for( ; i < length; i++ ){
        if( ( options = arguments[i] ) != null ){
            for( name in options ){
                src = target[ name ];
                copy = options[ name ];
                //防止死循环
                if( target === copy ){
                    continue;
                }
                //深层拷贝,拷贝的值非空,纯对象或者数组
                if( deep && copy && ( jQuery.isPlainObject(copy) || ( copyIsArray = jQuery.isArray( copy ) ) ) ){
                    //数组
                    if( copyIsArray ){
                        copyIsArray = false;
                        clone = src && jQuery.isArray( src ) ? src : [];
                    }else{
                        //对象
                        clone = src && jQuery.isPlainObject( src ) ? src : {};
                    }
                    target[ name ] = jQuery.extend( deep, clone, copy );
                }else if( copy !== undefined ){
                    target[ name ] = copy;
                }
            }
        }
    }
    return target;
}

24wangchen avatar Apr 17 '15 09:04 24wangchen