您的位置:首页 > Web前端 > JQuery

jQuery-源码详解一-框架设计

2015-03-25 10:21 686 查看
本来是想讲解下JavaScript的设计模式,不过感觉空谈模式再随便写两个例子与纸上谈兵无异,倒不如把jQuery这个优秀的框架给讲解一下,其中的设计理念(The Write Less,Do More)、整体架构都相当高明,设计模式、奇技淫巧也包罗万象,所以改道讲解jQuery了。

由于个人能力有限,有疑问或错误之处欢迎之处~~

先从jQuery的历史讲起:

jQuery在最开始发布的1.0版本是很简单的,只有CSS选择符、事件处理和AJAX交互3大块。其发展过程中,有几次重要的变革:

    ☑  1.2.3 版发布,引入数据缓存,解决循环引用与大数据保存的问题

    ☑  1.3 版发布,它使用了全新的选择符引擎Sizzle,在各个浏览器下全面超越其他同类型JavaScript框架的查询速度,程序库的性能也因此有了极大提升

    ☑  1.5 版发布,新增延缓对像(Deferred Objects),并用deferred重写了Ajax模块

    ☑  1.7 版发布,抽象出回调对象,提供了强大的的方式来管理回调函数列表。

我个人将jQuery分为七大模块:

1、选择器引擎

2、DOM操作

3、事件体系

4、异步回调

5、ajax交互

6、数据缓存

7、动画

如果再做细分,远不止这些模块,因为jQuery将很多共同的特性抽出做模块化了,更贴近单一职责的原则。

单一职责的好处是可以让我们很容易地来维护这个对象,比如,当一个对象封装了很多职责的时候,一旦一个职责需要修改,势必会影响该对象的其它职责代码。通过解耦可以让每个职责更加有弹性地变化。

讲解的jQuery源码版本一致为:1.11.2。

看jQuery的最外层的框架包装:(function( global, factory ) {

if ( typeof module === "object" && typeof module.exports === "object" ) {
module.exports = global.document ?
factory( global, true ) :
function( w ) {
if ( !w.document ) {
throw new Error( "jQuery requires a window with a document" );
}
return factory( w );
};
} else {
factory( global );
}

// Pass this if window is not defined yet
}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

//...

if ( typeof noGlobal === strundefined ) {
window.jQuery = window.$ = jQuery;
}

return jQuery;
}));我并不太清楚jQuery是从哪一个版本从原来的(function(window, undefined){ ... })(window);改成了现在这种方式。
两种方式异曲同工,都是为了解决命名空间与变量污染的问题,利用JavaScript函数作用域(在JavaScript中只有函数才具有作用域)的特性,采用立即调用的表达式包裹自身的方式解决这个问题。

将jQuery作为一个factory工厂参数传递到这个立即调用的函数表达式里面来,在这个表达式里进行调用这个factory,从而生成jQuery对象。其中的技巧有两个:

1、自执行的函数——构建jQuery对象

2、匿名函数——将jQuery工厂方法作为参数传递给自执行的函数。

按照我一贯偷懒的习惯,我写到这里就应该说拜拜了,不过既然要讲解jQuery,一篇blog里面怎么能没有点干货呢。

看招:// Define a local copy of jQuery
jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.fn.init( selector, context );
}
jQuery.fn = jQuery.prototype = {
//...
}
init = jQuery.fn.init = function( selector, context ) {
//...
};

// Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;jQuery是一个构造函数,而每次调用$(..)的时候都相当于new一个jQuery对象,但我们从来都没有使用new $()的方式。原因在于jQuery的构造函数实际上调用的是new jQuery.fn.init(...);也就是说每次调用$(..)都会实例化一个jQuery.fn.init对象,在下面jQuery将init.prototype指向了jQuery.fn,而jQuery.fn=jQuery.prototype,也就是jQuery.fn.init的原型指向了jQuery的原型,虽然每次我们实例化出来的是init的对象,但因为init的原型就是jQuery的原型,那么我们new出来的对象也就拥有jQuery原型中的所有方法和属性,从而省略了new操作符。
同样可以省略new操作符的含有一种技巧:var YUI = function() {
var i = 0,
Y = this,
args = arguments,
l = args.length,
instanceOf = function(o, type) {
return (o && o.hasOwnProperty && (o instanceof type));
},
gconf = (typeof YUI_config !== 'undefined') && YUI_config;

if (!(instanceOf(Y, YUI))) {
Y = new YUI();
} else {
//...
}
//...
return Y;
};YUI判断当前this对象不是YUI示例的时候,使用递归的方式在内部强制调用new操作符。同样可以省略new操作符。
而另一种用于生成对象的方式还有如下的方式:

jQuery.Callbacks = function( ) {

var self = {
//...
};

return self;
};上述的方式用于产生一个简单的对象,该函数只是用于生成该对象的一个简单工厂。在用于产生一个定义好的静态对象而不是单例对象的时候特别有用。同样也不存在new操作符。

以上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息