DevilPace 2014-08-01
作者:zccst
核心功能包括:
jQuery是如何定义的,如何调用的,如何扩展的。掌握核心方法是如何实现的,是理解jQuery源码的关键。这里理解了一切豁然开朗。
1,如何定义,即入口
//DefinealocalcopyofjQuery
varjQuery=function(selector,context){
//ThejQueryobjectisactuallyjusttheinitconstructor'enhanced'
returnnewjQuery.fn.init(selector,context,rootjQuery);//jQuery对象仅仅是构造函数jQuery.prototype.init加强版
}
2,jQuery的原型,及与jQuery.fn.init的关系
//定义对象方法,也即只有通过$("xx").的方式才能调用。
jQuery.fn=jQuery.prototype={
init:function(selector,context,rootjQuery){
returnjQuery.makeArray(selector,this);
}
其他还有很多属性和方法,
属性有:jquery,constructor,selector,length
方法有:toArray,get,pushStack,each,ready,slice,first,last,eq,map,end,push,sort,splice
...
}
//把jQuery.prototype赋给jQuery.prototype.init.prototype,是为了后面的实例化
//GivetheinitfunctionthejQueryprototypeforlaterinstantiation
jQuery.fn.init.prototype=jQuery.fn;
也即是,$("xx")拥有了实例方法,可以调用。(调用jQuery.prototype下定义的方法)
为什么jQuery要返回jQuery.fn.init对象?
jQuery=function(selector,context){
//ThejQueryobjectisactuallyjusttheinitconstructor'enhanced'
returnnewjQuery.fn.init(selector,context,rootjQuery);
}
jQuery.fn=jQuery.prototype={
……
}
jQuery.fn.init.prototype=jQuery.fn;
在stackoverflow上找到类似问题:
http://stackoverflow.com/questions/4754560/help-understanding-jquerys-jquery-fn-init-why-is-init-in-fn
还有这个
http://stackoverflow.com/questions/1856890/why-does-jquery-use-new-jquery-fn-init-for-creating-jquery-object-but-i-can/1858537#1858537
IbelievethecodeiswritteninthisfashionsothatthenewkeywordisnotrequiredeachtimeyouinstantiateanewjQueryobjectandalsotodelegatethelogicbehindtheobjectconstructiontotheprototype.TheformerIbelieveistomakethelibrarycleanertouseandthelattertokeeptheinitialisationlogiccleanlyinoneplaceandallowinittoberecursivelycalledtoconstructandreturnanobjectthatcorrectlymatchesthepassedarguments.
3,extend扩展对象方法和静态方法原理
jQuery.extend=jQuery.fn.extend=function(){
vartarget=arguments[0]||{};
returntarget;
}
使用extend就方便了,无非就是$.extend({});和$.fn.extend({});如果你能在看到fn时理解联想到是jQuery.prototype就好了。
再通过this作用域看一下:
$.extend->this是$->this.aa()
$.fn.extend->this是$.fn->this.aa()
附extend实现细节:
使用场景:
1,扩展一些函数
只有一个参数。例如:$.extend({f1:function(){},f2:function(){},f3:function(){}})
2,合并多个对象到第一个对象
(1)浅copy,第一个参数是目标对象。例如
vara={name:"hello"}
varb={age:30}
$.extend(a,b);//a={name:"hello",age:30}
(2)深copy,第一个参数是TRUE,第二个参数是目标对象。例如
vara={name:{job:"it"}};
varb={name:{age:30}};
//$.extend(a,b);
$.extend(true,a,b);
console.log(a);
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 if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // 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) ) { target = {}; } // 扩展插件的情况 extend jQuery itself if only one argument is passed if ( length === i ) {//$.extend({f1:function(){},f2:function(){},f3:function(){}}) target = this;//this是$,或是$.fn --i; } for ( ; i < length; i++ ) {//可能有多个对象扩展到第一个对象上 // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) {//options是一个对象 // Extend the base object for ( name in options ) { src = target[ name ]; //src是target里已经存在的value(也可能不存在) copy = options[ name ];//copy是待合入的一个value // 防止循环引用 Prevent never-ending loop if ( target === copy ) {//例如:var a={};$.extend(a,{name:a});//可能导致循环引用 continue; } // if是深复制else是浅复制 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 { 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;//target[ name ] = options[ name ]; } } } } // Return the modified object return target; };
jQuery.extend({...})分析
看一下是如何写的
jQuery.extend({
prop:""
method:function(){}
});
可以看出,这些方法是jQuery的静态属性和方法(也即是工具方法),将来既可以直接提供给用户使用,也可以在内部使用。
具体实现的工具属性和方法有(同时也标注了哪些在内部使用)
jQuery.extend({
expando:生成唯一JQ字符串(内部)
noConflict():防止冲突
isReady:DOM是否加载完(内部)
readyWait:等待多少文件的计数器(内部)
holdReady():推迟DOM触发
ready():准备DOM触发
isFunction():是否为函数
isArray():是否为数组
isWindow():是否为window
isNumeric():是否为数字
type():判断数据类型
isPlainObject():是否为对象自变量
isEmptyObject():是否为空的对象
error():抛出异常
parseHTML():解析节点
parseJSON():解析JSON
parseXML():解析XML
noop():空函数
globalEval():全局解析JS
camelCase():转驼峰
nodeName():是否为指定节点名(内部)
each():遍历集合
trim():去前后空格
makeArray():类数组转真数组
inArray():数组版indexOf
merge():合并数组
grep():过滤新数组
map():映射新数组
guid:唯一标识符(内部)
proxy():改this指向
access():多功能值操作(内部)
now():当前时间
swap():CSS交换(内部)
});
jQuery.ready.promise=function(){};监测DOM的异步操作(内部)
functionisArraylike(){}类似数组的判断(内部)
如果您觉得本文的内容对您的学习有所帮助,您可以微信: