以下这一段函数出现在实例化jQuery对象函数之后,是jQuery的prototype的最基本的几个函数,分析前先看这几个相关的常量和一些函数:
var deletedIds = []; var slice = deletedIds.slice; var concat = deletedIds.concat; var push = deletedIds.push; var indexOf = deletedIds.indexOf;
merge: function( first, second ) { var len = +second.length, j = 0, i = first.length; while ( j < len ) { first[ i++ ] = second[ j++ ]; } // Support: IE<9 // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) if ( len !== len ) { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first; }
map: function( elems, callback, arg ) { var value, i = 0, length = elems.length, isArray = isArraylike( elems ), ret = []; // 若是数组,则直接从0开始循环,每项都执行callback,返回值保存在ret中 if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } // 若是对象,就用for in循环,每项执行callback,返回值保存在ret中 } else { for ( i in elems ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } } // 返回ret的副本 return concat.apply( [], ret ); }
首先是最前面的几个常量,先定义了一个空数组,然后后面的几个slice等变量就直接等于了数组的slice操作,这样对于jQuery生成的类数组来说,直接调用这些方法可以很好的处理一些事情。在后面的源码分析中也可以这些函数很多的调用。
接下来是Jquery下的merge函数(这两个函数都不是在prototype下,而是直接是jQuery的属性),merge函数用于将两个数组或类数组合并,首先是用数组的形式一项项合并,然后为了支持类数组,又加了一个判断,对类数组做支持。
然后是map函数,map函数对给予的数组或对象进行遍历,针对每一项执行callback函数,ret中保存的是最后callback计算所得的值,组成数组后返回。
接下来就是jQuery中prototype最初定义的几个函数进行分析,代码和分析如下:
jQuery.fn = jQuery.prototype = { // 定义当前jquery的版本,同时设定好constructor的指向,方便后面使用 jquery: version, constructor: jQuery, // 初始选择器为空 selector: "", // 默认的jQuery类数组长度为0 length: 0, toArray: function() { return slice.call( this ); }, // 返回指定项的元素 // 或者返回所有元素组成的数组 get: function( num ) { return num != null ? // 如果存在num,则返回指定项元素 ( num < 0 ? this[ num + this.length ] : this[ num ] ) : // 不存在num,则返回数组副本 slice.call( this ); }, // 将一些列的elems放入新的JQuery中 // 返回的是根据elems生成的新的JQuery pushStack: function( elems ) { // 建立新的JQuery var ret = jQuery.merge( this.constructor(), elems ); // 将原始的JQuery对象放入prevObject中,方便后期返回 ret.prevObject = this; ret.context = this.context; // 返回新生成的对象 return ret; }, // each和map都是对数组或对象进行遍历 // 两者的区别在于,each遍历时,若某一项callback返回的是false,则停止遍历,最后返回的是经过处理的this // map则是将每一项传入的值进行计算,然后将结果组成一个数组返回 each: function( callback, args ) { return jQuery.each( this, callback, args ); }, map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, slice: function() { return this.pushStack( slice.apply( this, arguments ) ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, eq: function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); }, end: function() { return this.prevObject || this.constructor(null); }, // 最后的end可以对以上用pushStack过的方法进行回溯,回到上一步的操作对象 // 以下几个方法的添加使得JQuery更像数组 push: push, sort: deletedIds.sort, splice: deletedIds.splice };