1.闭包结构
(function(window,undefined){
....
....
})(window)
jquery整体的内部实现都包含在一个立即执行函数形成的闭包里,只向外暴露jquery和$两个变量,避免了全局变量的污染。
2.实例化jquery对象
平时我们实例化jquery对象的时候,并不是像实例化普通对象一样,使用new来实例化,而是直接$(“XXX”),这也是jquery的一个亮点,jquery是如何来实现这一点的呢?
(function(window, undefined) {
var
// ...
jQuery = function(selector, context) {
return new jQuery.fn.init(selector, context, rootjQuery);
},
jQuery.fn = jQuery.prototype = {
init: function(selector, context, rootjQuery) {
...
}
}
jQuery.fn.init.prototype = jQuery.fn;
})(window);
以上是创建jquery实例的核心代码,主要总结下来有以下几点:
a.在使用$(“XXX”)实例化jquery对象的时候,实际上调用jquery原型上的init方法。实例化的工作实际是init完成的。
b. jquery.fn=jquery.prototype;
b.为了让jquery实例能够访问到jquery原型上的方法,jquery做了这样的处理:jQuery.fn.init.prototype = jQuery.fn;
3.方法的重载
// 获取 title 属性的值
$('#id').attr('title');
// 设置 title 属性的值
$('#id').attr('title','jQuery');
// 获取 css 某个属性的值
$('#id').css('title');
// 设置 css 某个属性的值
$('#id').css('width','200px');
jquery中通过实现方法的重载,通过传入参数的不同,实现不同的功能,使用起来非常方便。
4.jquery的扩展
在jquery中使用jquery.fn.extend 与 jquery.extend用来进行jquery方法的扩展。
jquery.extend()用来扩展jquery的对象方法,也就是我们通过$.method()调用的方法。
jquery.fn.extend()用来扩展jquery的实例方法,也就是jquery实例所具有的方法。$(“XXX”).method();
关于这两个方法,看源码后我们会发现,他们实际上是基于同一个函数实现的。因为this的指向不同,来达到不同的功能。即:
$.extend=$.fn.extend=function(){
}
关于这里的这个function所做的事情,实际上做的就是一个对象克隆的工作,类似Object.assign(),但Object.assign()只能实现浅克隆,$.extend()可以通过设置第一个参数为true来实现深克隆。
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[ 0 ] || {}, //第一个参数
i = 1,
length = arguments.length,
deep = false; //是否深克隆
// Handle a deep copy situation
//如果都一个参数为boolean 则为是否开启深递归 target指向下一个参数
if ( typeof target === "boolean" ) {
deep = target;
// Skip the boolean and the target
target = arguments[ i ] || {};
i++;
}
// Handle case when target is a string or something (possible in deep copy)
// 如果传入的第一个参数是 字符串或者其他
if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
target = {};
}
// Extend jQuery itself if only one argument is passed
// 如果只有一个参数
if ( i === length ) {
target = this;
i--;
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
// 将每个源的属性全部复制到 target 上
if ( ( options = arguments[ i ] ) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
// 防止有环,例如 extend(true, target, {'target':target});
if ( target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
//如果深克隆开启且copy为对象或数组
//这里判断还可以用Object.prototype.toString.call(copy) 返回"[object Array]或[object Object]"
if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
( copyIsArray = Array.isArray( copy ) ) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && Array.isArray( src ) ? src : [];
} else {
clone = src && jQuery.isPlainObject( src ) ? src : {};
}
// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );
// Don't bring in undefined values
// 浅克隆
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
5.链式调用
另一个让大家喜爱使用 jQuery 的原因是它的链式调用,这一点的实现其实很简单,只需要在要实现链式调用的方法的返回结果里,返回 this ,就能够实现链式调用了。