0 0 0 0

Preface preface

In fact, this analysis of the jquery source series is a long idea of my own, of course, because of the previous and understanding. Most recently read books, fire me the desire, and then start to implement this plan.

Why do you want to choose the jquery source, I'm looking for a? Jquery 's appearance is a very powerful weapon for many of the first people. Why don't jquery be so popular, deep. I think that is the api design for jquery.

In the design of jquery, the most important two is ( a person view ):

  • Provide tool methods;
  • The action of the dom element, including selection, property values, etc. For a library, the first point is that there's no basic tool method, how to become a library.

For javascript, the most important one is dom operatio &, and jquery is a huge contribution to the dom operation, so many beginners are now not able to use the native js api ( for example, document, bates, and so on ) to encapsulate a very simple delegate api for complex dom operatio & ( unlike the dom operating interface ) for complex dom operatio &: The write less, do more .

The version of jquery I chose is 1. 9. 0, and it must be the simplest part of jquery first.

1. External sandbox and namespace $.

Almost a bit of experience, in order to avoid declaring some global variables and pollution, put the code in a sandbox execution, and then expose the namespace ( api, function, object ):

(function( window,undefined){//用一个函数域包起来,就是所谓的沙箱//在这里边var定义的变量,属于这个函数域内的局部变量,避免污染全局//把当前沙箱需要的外部变量通过函数参数引入进来//只要保证参数对内提供的接口的一致性,你还可以随意替换传进来的这个参数"use strict"; window.jQuery = window.$ = jQuery;})( window );

There's a question, why is the second argument undefined? Here, jquery has a small strategy for compression.

Read the following code:

(function( window,undefined){var a =undefined;if(a ==undefined){blabla...}....if(c ==undefined)return;})( window );

After compression, can become:

(function(w, u){var a = u;if(a == u){blabla...}....if(c == u)return;})(w);

Because this outer function only passes one parameter, u won't normally be undefined when the sandbox is executed, with 9 letters down to 1 letters, you can see. In comments, nodejser also gives another solution to the supplemental of undefined:

Undefined before ECMAScript5 is writable, as well as undefined can be assigned to. The purpose of the jquery writer to do so is to prevent the 2b from assigning an unexpected bug to the undefined.

In the sandbox, the first sentence"use strict"is a strict mode of using JavaScript, which is quite a string for low-level browsers, so compatibility isn't a problem.

Finally, jquery exposes a global namespace jquery ( for writing simpler, a shorthand is $, and fortunately javascript uses $ to do variables named legal ).

In fact, jquery is a function and why it's designed because:

  • The function is also an object, so you can bind tool methods on the namespace of jquery
  • A function can have prototype prototype, which is essentially dom = new jquery ("# id") whenever it comes through dom = $ ("# id"); if you know the prototype, you know that if you bind the method on jquery, you can call these methods if you've a prototype that's bound to it.

Simply, as a class, the binding method on the prototype is equivalent to the member method, binding tool methods on jquery, equivalent to static methods of the class, as follows:

jQuery.A =function(){};jQuery.prototype.B =function(){};


Class jQuery{publicstatic A(){}public B(){}}

ideas are reflected in jquery, and a lot of thinking that ideas guide how to design a more reasonable api that's to the library. The so-called encapsulation, inheritance, and all is for the next purpose, how to design a better api, I think that's the essence.

2, the core tools for jquery

The following method is a tool method defined at the core of jquery ( you can go to github 's jquery project scilab ), and core is the core part of the jquery, so it's the most important part of the jquery: A $. Trim ( ) removes the space at both ends of the string. ( internal call 7 ) $. Each ( ) iterates through arrays or objects, which are used many times within jquery, with a few good usage, after parsing, and further examples. ( internal call 59 ) $. Class1 ( ) returns a value in an array of index locations. If the value isn't in the array, retur & 1. ( internal call 9 ) $. Grep ( ) lymphocytes return elements that correspond to a standard in an array. ( internal call 6 ) $. Merge ( ) merges two arrays. ( internal call 11 ) $. Map ( ) converts elements from an array into another array. ( internal call 12 ) $. MakeArray ( ) the object into an array. ( internal call 6 ) $. GlobalEval ( ) executes a script under global scope. ( internal call 2 ) $. Proxy ( ) accepts a function and returns a new function, and the new function always keeps a specific context context. ( internal call 0 ) $. Nodename ( ) returns the node name of the dom node, or determines whether the dom node name is a member name. ( internal call 51 ) $. Extend ( ) lymphocytes combine multiple objects into the first object. ( internal call 42 )

All of the following are the types of judgment, and this article is just a discussion of $. Type, and the method of isXXX is to call $. Type to implement it. A $. Type ( ) lymphocytes determine the category of objects ( function objects, date objects, array objects, regular objects, and so on ). Implementation of this method is to use $ and each. ( internal call 65 ) $. Isarray ( ) determines whether a parameter is an array. ( internal call 12 ) $. IsEmptyObject ( ) determines whether an object is null ( without any attributes ). ( internal call 4 ) $. Isfunction ( ) determines whether a parameter is a function. ( internal call 32 ) $. IsPlainObject ( ) determines whether a parameter is created with an object that's created with % % rtt or new object. ( internal call 4 ) $. IsWindow ( ) determines whether the object is a window object. ( internal call 6 )

The following three functions are simpler and no need to parse the article. A $. Noop ( ) an empty function that's thought to be used as a default callback function without having to define an empty function co & uming resource. ( internal call 2 ) $. Now ( ) gets the current timestamp, which is simple: Return ( new date ( ) ), gettime ( ). ( internal call 4 ) $. Error ( ) erro & that throw an exception outside of the code is simple: Throw new error ( msg ). ( internal call 2 )

All of the following three is used primarily when the ajax process returns data, where parsejson is used in the actual project, often used to parse a piece of text into json format $. ParseHTML ( ), and then write a separate section. ( internal call 2 ) $. Parsejson ( ) parsing json, followed by a separate section. ( internal call 2 ) $. Parsexml ( ) parse xml, followed by a separate section. ( internal call 1 )

I think it's an internal auxiliary function as follows: $. Access ( ) this function I think is the auxiliary function inside jquery, and there's no need to leak out, internally used to go to some of the object 's attribute values. ( internal call 9 ) $. Camelcase ( ) converted to. ( internal call 12 )

Start looking at the source.

2. 0 before starting.

In the beginning of jquery, there's a small segment.

 class2type ={}, core_deletedIds =[], core_version ="1.9.0",//Save a reference to some core methods core_concat = core_deletedIds.concat, core_push = core_deletedIds.push, core_slice = core_deletedIds.slice, core_indexOf = core_deletedIds.indexOf, core_toString = class2type.toString, core_hasOwn = class2type.hasOwnProperty, core_trim = core_version.trim,//等同以下代码: core_concat =Array.prototype.concat, 

If you need to call concat, you can call the following method to unde & tand how call is unde & tood by the usage of the apply,: ) var arr = [ ];. Arr. Concat ( );: Core_concat. Call ( arr ); three: Core_concat. Apply ( arr ).

Think about 2 problems:

  • Why do you want to store these methods first.
  • Why do jquery use two or three, rather than a way to use it directly. The only reason that I think the author does so is because of the efficiency problem. Here's my understanding:

When you call the method concat for I & tance sids, you fi & t need to identify the type of the current I & tance balancers is array, finding the concat memory entry for array in memory space, pushing the pointer and other paramete & of the current object balancer to the, jump to the concat address. When you save the entry core concat of the concat method, you can completely eliminate the first two steps to improve performance. In the comments, nodejser also gives another answer: var obj = % 7B % 7D; calls obj. Concat at this time is illegal, but if jquery uses two or three, it can solve this problem. That's, the method that allows the class array to be used by the array ( which is another usage brought by call versus apply ), and it's perfect to use this method!

2. 1 $. Trim.

Jquery 's trim function is used to remove the string from both ends of the string ( 7 times in the jquery source ), which is also a high frequency, because it's often

Usage: $. Trim ("front end") = = ="front end"".

Jquery 's trim source is as follows:

core_version ="1.9.0",core_trim = core_version.trim,rtrim =/^[suFEFFxA0]+|[suFEFFxA0]+$/g,trim: core_trim &&!"uFEFFxA0")?function( text ){return text ==null?"": text );}://Otherwise use our own trimming functionalityfunction( text ){return text ==null?"":( text +"").replace( rtrim,"");}


var core_trim = String. prototype. trim; ( core_trim & amp; & amp;! core_trim. Call ("ufeffxa0") ) equivalent to: If ( string. Prototype. Trim & amp; & amp; ufeffxa0. Trim ( )! = => )>>> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> ) jquery. "ufeffxa0. Trim ( )! = =>".

A ufeff is a byte order tag for utf8, as shown in: In byte order, is the space. If the above conditions are set up, then the native trim function is used directly, and the expansion is the.

$.trim =function( text ){return text ==null?"": text.trim();}

If the above conditions aren't set up, then jquery implements a trim method:

$.trim =function( text ){return text ==null?"":( text +"").replace( rtrim,"");}

And, of course, you've to see the regular expression.

2. 2 $. Each.

Jquery 's each is the most frequently used method, in which it's also using a very frequent api ( 59 ), making it very concise to traverse an array or object code snippet.

Let's start with a few examples of each:

//each接受2个参数, 数组[1,2,3],回调函数$.each([1,2,3],function(key, value){ console.log("["+ key +"]="+ value);returnfalse;});//输出:[0]=1[1]=2[2]=3[1,2,3]//可以看到回调函数具有两个参数,key是数组的索引,value是对应的元素//each接受3个参数, 数组[1,2,3],回调函数,一个额外的参数数组args=[4,5]$.each([1,2,3],function(arg1, arg2){ console.log(this+","+ arg1 +","+ arg2);},[4,5]);//输出:1,4,52,4,53,4,5[1,2,3]//可以看到回调函数的两个参数就是each的第三个参数args,在函数里边的this就是遍历元素自己

And then we look at the each implementation of jquery.

//其实我觉得jQuery这段each代码写得一点也不好//代码重复率太高了!我下边对它进行解析并改造//貌似看注释是为了让代码运行更快,具体没测试。//源码如下$.each =function( obj, callback, args ){//obj 是需要遍历的数组或者对象//callback是处理数组/对象的每个元素的回调函数,它的返回值实际会中断循环的过程//var value, i =0, length = obj.length, isArray = isArraylike( obj );//判断是不是数组if( args ){if( isArray ){//数组for(; i < length; i++){ value = callback.apply( obj[ i ], args );//相当于://args = [arg1, arg2, arg3];//callback(args1, args2, args3)。然后callback里边的this指向了obj[i]if( value ===false){//注意到,当callback函数返回值会false的时候,注意是全等!循环结束break;}}}else{//非数组for( i in obj ){//遍历对象的做法 value = callback.apply( obj[ i ], args );if( value ===false){break;}}}//A special, fast, case for the most common use of each}else{if( isArray ){for(; i < length; i++){ value = obj[ i ], i, obj[ i ]);//相当于callback(i, obj[i])。然后callback里边的this指向了obj[i]if( value ===false){break;}}}else{for( i in obj ){ value = obj[ i ], i, obj[ i ]);if( value ===false){break;}}}}return obj;}

The implementation of each is simpler, but I don't understand why the implementation of jquery needs so long, if jquery is written in more than the longer code, I'd

//我改写的版本//这里并不是代表我的代码没有bug,for in对于数组来说性能比较低而且存在某些bug//这里想表达的意思只是我希望用更简洁的代码来减少原先代码的重复性$.each =function( obj, callback, args ){var value, i =0, length = obj.length;for( i in obj ){ value = args ? callback.apply( obj[ i ], args ): obj[ i ], i, obj[ i ]);if( value ===false){break;}}return obj;}

Learn about the use of $. Each because the each function will be used more than once in the following profiling. : )

2. 3 $.

Jquery 's inarray implementation is simpler, and there's a little point here to discuss, as follows:

core_deletedIds =[],core_indexOf = core_deletedIds.indexOf,//相当于 core_indexOf = Array.indexOf;//elem 规定需检索的值。//arr 数组//i 可选的整数参数。规定在数组中开始检索的位置。它的合法取值是 0 到 arr.length - 1。如省略该参数,则将从数组首元素开始检索。inArray:function( elem, arr, i ){var len;if( arr ){//原生的Array对象支持indexOf方法,直接调用if( core_indexOf ){return arr, elem, i );} len = arr.length;//当i为负数的时候,从数组后边len+i的位置开始索引 i = i ? i <0?Math.max(0, len + i ): i :0;for(; i < len; i++){//Skip accessing in sparse arrays//jQuery这里的(i in arr)判断是为了跳过稀疏数组中的元素//例如 var arr = []; arr[2] = 1;//此时 arr == [undefined, undefined, 1]//结果是 => (0 in arr == false) (1 in arr == false) (2 in arr == true)//但是不解的是这里//测试了一下 $.inArray(undefined, arr, 0)是返回-1的//也许你很不解,因为数组中明明第一个元素就是undefined,后边举个例子探讨一下if( i in arr && arr[ i ]=== elem ){return i;}}}//全部都不符合,返回-1return-1;},

Test it ( under firefox ): An var arr = [ undefined, 1 ]; output is: = = [ undefined, 1 ] 0 in arr = = true; arr. Indexof ( undefined ) = = 0; arr [ 0 ] = = undefined, but if the following code: var arr = [ ]; a [ 1 ] = 1; output is: Arr = = [ undefined, 1 ] 0 in arr = = false; arr. Indexof ( undefined ) = = -1; arr [ 0 ] = = undefined.

It shows that in the second case ( the sparse array referred to in the comment ), it isn't just through the [ I _ I ] = = = to get a more than one condition I in

2. 4 $. Grep.

Jquery 's grep is in order to pass in an array elems, after the filter callback, wait until the filtered result. A callback is a filter, $. Grep is filtered according to its return value. Inv true indicates that the callback filter returned true those filtered out. It's a bit round, looking at two small examples. It's entirely clear:

$.grep([0,1,2],function(n,i){return n <=0;});//结果是:[0] $.grep([0,1,2],function(n,i){return n <=0;},true);//结果是:[1, 2]

It's easy to implement, but it doesn't know that the order of arguments accepted here's not consistent with the callback of $. Each, and I think this is the reason that the filter is often designed to use value so that the second argument can be ignored. The code is as follows:

grep:function( elems, callback, inv ){var retVal, ret =[], i =0, length = elems.length; inv =!!inv;//转成布尔型//Go through the array, only saving the items//that pass the validator functionfor(; i < length; i++){ retVal =!!callback( elems[ i ], i );//注意这里的callback参数是先value,后keyif( inv !== retVal ){ ret.push( elems[ i ]);}}return ret;}

2. 5 $. Merge.

A $. Merge ( [ 0, 1, 2 ], [ 2, 3, HSPA ] ) = = [ 0, 1, 2, 2, 4, the two paramete & for the ] merge must be an array, which makes it at the end of the fi & t array. Just from an example or a description, two parameters of the merge function seem to be an array, but look at its source code to know that there's a little detail. A $. Merge ( ) source code is as follows:

merge:function( first, second ){//难道first 跟second参数必须为数组?var l = second.length, i = first.length, j =0;//从这个判断来看,second可以是一个对象if(typeof l ==="number"){//如果second是数组for(; j < l; j++){ first[ i++]= second[ j ];}}else{//如果second不是数组//假设second = {}; second[0] = 1; second[1] = 2; second[2] = 3;//那这里的逻辑也是可以成立的while( second[j]!==undefined){ first[ i++]= second[ j++];}} first.length = i;return first;}

From the above source code, the first parameter looks like the 's merge function, in fact, first = % 7blength: 3 % rtt; first [ 0 ] = 1; first [ ] = 3. Of course, the purpose of this analysis is to think of the flexibility of JavaScript, and we should make sure that both parameters are array types, avoid code that's hard to unde.

2. 6 $. Map.

From $. Map code, it's fairly easy to understand that each item after the callback is processed into the returned array is added to the return array.

$.map([0,1,2],function(n){return n +4;});//结果:[4, 5, 6]

A $. Map source code is as follows:

core_deletedIds =[],core_concat = core_deletedIds.concat,//arg is for internal usage onlymap:function( elems, callback, arg ){var value, i =0, length = elems.length, isArray = isArraylike( elems ), ret =[];//Go through the array, translating each of the items to theirif( isArray ){for(; i < length; i++){ value = callback( elems[ i ], i, arg );if( value !=null){//如果返回值是null,则不加入结果中 ret[ ret.length ]= value;}}//Go through every key on the object,}else{for( i in elems ){ value = callback( elems[ i ], i, arg );if( value !=null){ ret[ ret.length ]= value;}}}//Flatten any nested arrays//这里相当于 var a = [];a.concat(ret)return core_concat.apply([], ret );},

But see the last sentence of the map implementation code, and why don't you go straight back. It's very confusing to start here, but if you look at the following example, you're going to be a big one.

$.map([0,1,2],function(n){return[ n, n +1];});//输出:[0, 1, 1, 2, 2, 3]//如果是return ret的话,输出将会是:[[0,1], [1,2], [2,3]]

in w3cschool is a bad description of this method: Map ( index, domelement ), actually, should be: Map ( callback, index ) )

2. 7 $. MakeArray.

A $. MakeArray converts an array object to an array object with a simple source code, as follows:

makeArray:function( arr, results ){var ret = results ||[];//不由得不赞js这个技巧//等同于:var ret = (!results)? [] : results;if( arr !=null){if( isArraylike(Object(arr))){//如果arr是一个类数组对象,调用merge合到返回值 jQuery.merge( ret,typeof arr ==="string"?[ arr ]: arr
 );}else{//如果不是数组,则将其放到返回数组末尾//等同于ret.push(arr); ret, arr );}}return ret;},

2. 8 $. GlobalEval.

Look at the name. This is a variant of eval, and its scope is under window, of course, with the call method. The source code is:

//Evaluates a script in a global context//Workarounds based on findings by Jim Driscoll// data ){if( data && jQuery.trim( data )){//We use execScript on Internet Explorer//We use an anonymous function so that context is window//rather than jQuery in Firefox( window.execScript ||function( data ){ window["eval"].call( window, data );})( data );}},


globalEval:function( data ){if( data && jQuery.trim( data )){//data不是空字符串var fn = window.execScript;//在IE跟旧版本的Chrome是支持此方法的if(!window.execScript){//新版浏览器没有此api fn =function( data ){ window["eval"].call( window, data );//这里为何不能直接 window, data );//查了以下,在chrome一些旧版本里 window, data )无效 }} fn(data);}},

Why do you need globalEval. What's the difference with eval. I think the following scenarios need to be used: A. Js dynamically loads the contents of b. Js in a function domain and then executes. The code for b. Js is: In function B ( ) % 7b %, it's expected that the b function burst leak in the global domain. If eval is used in a. Js, b can make it only a function within a local domain, so you must borrow the globalEval method. In the jquery source, there's a globalEval figure for the script in the action dom and the ajax script.

2. 9 $. Proxy.

This function is less than that, and I think it'll cause some confusion, so it isn't much easier to replace it with some better ways of understanding it. The source code is:

//Bind a function to a context, optionally partially applying any//arguments.proxy:function( fn, context ){var tmp, args, proxy;if(typeof context ==="string"){ tmp = fn[ context ]; context = fn; fn = tmp;}//Quick check to determine if target is callable, in the spec//this throws a TypeError, but we will just return undefined.if(!jQuery.isFunction( fn )){returnundefined;}//Simulated bind//由此看出,proxy的参数必须是2个,否则有无法预料的bug args = arguments,2); proxy =function(/*arguments*/){//需要注意到的是这里的arguments是当前函数的参数列表return fn.apply( context ||this, args.concat( arguments )));};//Set the guid of unique handler to the same of original handler, so it can be removed//之后再探讨以下guid是做什么的 proxy.guid = fn.guid = fn.guid || jQuery.guid++;return proxy;},

At first glance, the arguments in the above proxy function are confused with the arguments of its outer layer. Example example:

function a(){ console.log(arguments);//输出[1,2,3,4,5]}var b = $.proxy(a,this,1,2,3);//这里arguments = [a, this, 1, 2, 3];b(4,5);//这里arguments = [4,5];

If the analysis isn't accurate enough to treat the above output as [ 1, 2, 3 ] unde & tanding the arguments of the proxy, you know args in the proxy function. Concat ( core_slice. Call ( arguments ) ) actually [ 1, 2, servicecontroller ]. Concat ( [ 4 ).

2. 10 $. Nodename.

The nodename function is to get the node name of the dom node or determine whether its name matches the incoming parameter. Code is simple, here you can see a technique that's used in JavaScript. ( see code comments ) source code:

nodeName:function( elem, name ){//IE下,DOM节点的nodeName是大写的,例如DIV//所以统一转成小写再判断//这里不return elem.nodeName.toLowerCase();//我认为原因是为了保持浏览器自身的对外的规则,避免所有引用nodeName都要做转换的动作return elem.nodeName && elem.nodeName.toLowerCase()=== name.toLowerCase();//可以看到这里的&&使用技巧,以上代码等同于://if (elem.nodeName) return elem.nodeName.toLowerCase() === name.toLowerCase();//else return elem.nodeName;//如此之简洁},

2. 11 $. Type.

Next, you just need to introduce the type function, which is a good practice for $. Each. Learn about typeof and tostring:

typeof1=='number'typeof{}=='object'typeof[]=='object'(1).toString()=="1"({}).toString()=="[object Object]"//再针对一些边界的测试,typeofnull=="object"typeofundefined=="undefined"(null).toString()//非法(undefined).toString()//非法//再看看很诡异的几个:([]).toString()==""(newError()).toString()=="Error"//出现以上两个的结果的原因是,Array跟Error类重写了toSting方法//如果用Object的toString方法的话,就是一下结果[])=="[object Array]""[object Error]"

After reading the above experiments, look back at the $. Type function, which acts as a typeof operator, and is simply: A $. Type = function ( obj ) % 7b 7b; but for an array, it's an object, and typeof doesn't distinguish that it's an array type, and jquery extends the type method for some special objects such as null, window, regexp, and so on, for some special objects such as null, window, regexp. It first takes a common type of table ( meaning that there's a hash table class2type ), as follows:

//Populate the class2type mapjQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(""),function(i, name){ class2type["[object"+ name +"]"]= name.toLowerCase();});$.type =function( obj ){if( obj ==null){//如果是null或者undefined,直接转成String返回//注意到这里是==而不是===returnString( obj );}//RegExp,Array等都属于Object//为了精准判断类型,借由Object.prototype.toString跟class2type表//这里为什么要用core_toString而不用obj.toString的原因在刚刚试验中说明了returntypeof obj ==="object"||typeof obj ==="function"? class2type[]||"object":typeof obj;},

IsXXX isn't in detail here. The source is as follows.

//See test/unit/core.js for details concerning isFunction.//Since version 1.3, DOM methods and functions like alert//aren't supported. They return false on IE (#2968).isFunction:function( obj ){return jQuery.type(obj)==="function";},isArray:Array.isArray ||function( obj ){return jQuery.type(obj)==="array";},isWindow:function( obj ){return obj !=null&& obj == obj.window;},isNumeric:function( obj ){return!isNaN( parseFloat(obj))&& isFinite( obj );},isPlainObject:function( obj ){//Must be an Object.//Because of IE, we also have to check the presence of the constructor property.//Make sure that DOM nodes and window objects don't pass through, as wellif(!obj || jQuery.type(obj)!=="object"|| obj.nodeType || jQuery.isWindow( obj )){returnfalse;}try{//Not own constructor property must be Objectif( obj.constructor &&!,"constructor")&&!,"isPrototypeOf")){returnfalse;}}catch( e ){//IE8,9 Will throw exceptions on certain host objects #9897returnfalse;}//Own properties are enumerated firstly, so to speed up,//if last one is own, then all properties are own.var key;for( key in obj ){}return key ===undefined|| obj, key );},isEmptyObject:function( obj ){var name;for( name in obj ){returnfalse;}returntrue;},

2. 12 $. Extend.

The extend function ( note that extends is a reserved keyword in js, so there's no s at the end of the name ) is a function that uses high frequencies, usually you write a. For example:

varPlugin=function(opt){//opt为传入的配置this.opt = $.extend({'title':'默认标题','content':'默认内容'}, opt);};var p =newPlugin({title:'传入标题'})

The $. Extend source code is as follows:

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 situationif(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 passedif( length === i ){//$("#id").extend(dest)的时候 target =this;--i;}for(; i < length; i++){//可以传入多个复制源//Only deal with non-null/undefined valuesif((options = arguments[ i ])!=null){//Extend the base object//将每个源的属性全部复制到target上for( name in options ){ src = target[ name ]; copy = options[ name ];//Prevent never-ending loopif( target === copy ){//防止有环,例如 extend(true, target, {'target':target});continue;}//Recurse if we're merging plain objects or arraysif( deep && copy &&( jQuery.isPlainObject(copy)||(copyIsArray = jQuery.isArray(copy)))){//如果是深复制if( copyIsArray ){ copyIsArray =false;//这句话我认为是多余的。//克隆原来target上的原属性 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//可以看到undefined的属性对时不会复制到target上的}elseif( copy !==undefined){ target[ name ]= copy;}}}}//Return the modified objectreturn target;};

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = at this point, some external methods that bind to = = = = = = = = = = = here, some of the external methods that are bound to = = = = = = = = =. The next article discusses the processing of the ready events.

Copyright © 2011 Dowemo All rights reserved.    Creative Commons   AboutUs