jQuery源码解析

335 阅读1分钟

开源库分析

前端开源库分为无模块时代和有模块时代,jQuery是无模块时代的代表;

jQuery框架亮点

1、利用工厂模式,无new化构建对象;
2、模块划分明确;
3、开闭原则的优秀体现;
4、优秀的参数处理(多态、健壮性);
5、模块支持检测;

工厂模式

//最外层架构,匿名自执行函数
(function (window, undefined) {
    //建立一个工厂方法,你只需要告诉工厂你需要什么,它就可以返回什么
    function jquery() {
        return jquery.fn.init();
    }
    jquery.prototype = {
        init: function () {

        }
    };
    window.jquery = jquery;
    window.$ = jquery;
    //利用引用类型的特点,共享原型
    jquery.prototype = jquery.fn = jquery.prototype.init.prototype;
})(window, undefined);

为什么这么设计?window明明随时都可以获取的到?
作用域链的影响,查找变量是逐级向上查找。为了减少作用域链查找时间。

传undefined也是这个原理,那为什么不传null?
undefined相对于js是个变量,而null是个关键字。

jQuery最内层暴露的是一个工厂方法,但是vue暴露的是类的方式,为什么?
vue项目只需要一个实例,其他的都是组件;而jQuery需要创建大量的dom对象。

为什么$.css()、$('#id').css()等都可以调用?
利用共享原型的特点,jquery.prototype = jquery.fn = jquery.prototype.init.prototype;

模块划分明确

为什么jquery不把所有的方法都写到jquery.prototype中,像下面这样

jquery.prototype = {
        init: function () {

        },
        css: function () {

        },
        hide: function () {

        },
        show: function () {

        },
    };

缺点很明显,阅读维护非常不方便;那jquery采用什么方式来解决这个模块划分的了?
jquery是根据功能划分为多个模块,像样式设置模块(css、hide、style等),工具类模块,异步模块等,每个模块用对象封装扩展到jquery上,现在模块化划分清晰,后期的扩展也方便;

 jquery.extends = function () {

    }
    jquery.extends({
        css: function () {

        }
    });
    jquery.extends({
        isArray: function () {

        }
    });

jquery.extends的实现方式?
jquery.extends中传入一个参数和传入多个参数的处理方式不一样,为了代码不要看起来那么累赘,采用了享元模式;
享元模式:目的减少对象的数量,做法把这些对象分析,分析出私有的数据和方法,分析出公用的数据和方法;

   //不考虑深拷贝参数的影响,只考虑$.extends(obj)将对象扩展到jquery上,$.extends(obj1,obj2)将obj2扩展到obj1上
    //享元模式,减少相同代码块数量
    jquery.extends = function () {
        var target = arguments[0] || {};
        var length = arguments.length;
        var i =1;
        if(length === 1){
            target = this;
            i--;
        }
        for(var name in arguments[i]){
            target[name] = arguments[i][name];
        }
    }

模块支持检测

 //模块支持检测
    if(typeof define === 'function' && define.amd && define.amd.jquery){
        define('jquery',[],function(){
            return jQuery;
        });
    }