学习jQuery源码(一)- 整体架构

整体架构

无new构建实例

总结

  • 通过 new jQuery.fn.init() 构建一个新的对象,拥有 init 构造器的 prototype 原型对象的方法
  • 通过改变 prototype 指针的指向,让这个新的对象也指向 jQuery 对象的原型 prototype
  • 这样构建出来的对象就继承了 jQuery.fn 原型定义的所有方法了

原理图示:
原理图示

链式调用

待补充。。。

插件接口

jQuery 支持自己扩展属性,对外提供了一个接口,jQuery.fn.extend() 来对对象增加方法

在jQuery中,接口方法的定义是这样的:

jQuery.extend = jQuery.fn.extend = function(){}

也就是说,两者指向的是同一个函数。前者是对 jQuery 本身的属性和方法进行拓展;后者是对 jQuery.fn,也就是 jQuery 的原型的属性和方法进行了拓展。而这样的功能就是通过 this 来实现。
源码:

jQuery.extend = jQuery.fn.extend = function(){
var src, copyIsArray, copy, name, options, clone,
target = arguments[0] || {} // 常见用法 jQuery.extend( obj1, obj2 ),此时,target 为 arguments[0]
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if( typeof target === "boolean" ){ // 如果第一个参数为 true,即 jQuery.extend( true, obj1, obj2 ); 的情况
deep = target; // 此时 target 为 true
target = arguments[1] || {}; // target 改成 obj1
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if( typeof target !== "object" && !jQuery.isFunction(target) ){ // 处理奇怪的情况,例如 jQuery.extend( 'hello', { nick: 'casper' } )
target = {};
}
// extend jQuery itself if only one argument is passed
if( length === i ){ // 处理类似这种情况:jQuery.extend(obj),或jQuery.fn.extend(obj)
target = this; // jQuery.extend 时,this 指的是 jQuery;jQuery.fn.extend 时,this 指向 jQuery.fn
--i;
}
for( ; i < length; i++ ){
// Only deal with non-null/undefined values
if( (options = argument[i]) != null ){ // 比如 jQuery.extend( obj1, obj2, obj3, obj4 ), options 则为 obj2、obj3……
// Extend the base object
for( name in options ){
src = target[name];
copy = options[name];
// Prevent never-ending loop
if( target === copy ){ // 防止自引用
continue;
}
// Recurse if we're merging plain objects or arrays
// 如果是深拷贝,且被拷贝的属性值本身是个对象
if( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ){
if( copyIsArray ){ // 被拷贝的属性值是个数组
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else { // 被拷贝的属性值是一个 plainObject,比如 { nick: 'casper' }
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
target[name] = jQuery.extend( deep, clone, copy ); // 递归
} else if( copy !== undefined ){ // 浅拷贝,且属性值不为 undefined
target[name] = copy;
}
}
}
}
// Return the modified object
return target;
}

Reference

Aaron - jQuery 2.0.3 源码分析core - 整体架构