// HANDLE: $(function) // 处理入口函数简写 } else if (jQuery.isFunction(selector)) { //JQuery.isFunction()判断是不是函数,$(function(){})这种,是的话 return rootjQuery.ready(selector); //返回$(document).ready(function(){}), } //处理$($('#div')) 这种怪癖的写法 if (selector.selector !== undefined) { this.selector = selector.selector; //就把'#div'这个字符串给this,相当于$($('#div')) -> $('#div') this.context = selector.context; //这个步骤就是把查找域给this } return jQuery.makeArray(selector, this); },
比较简单的代码直接注释中解释,重点来说说jquery中的makeArray方法
var e=null; console.log( $.makeArray(e) ) //打印[], console.log( $.makeArray({ a:1,b:2 })) //打印[{ a:1,b:2 }] console.log( $.makeArray( {'0':1 ,'1':2} )); //打印[{'0':1 ,'1':2}] console.log( $.makeArray( {'0':1 ,'1':2,'a':'哈哈',length:2} ));// [1,2]
以上结果说明,null 或 undefined通过$.makeArray就会变成[],没有length属性的对象会把对象当成一个元素,生成一个数组,有length属性的,首先除了数字字符属性其他属性名的都不要,然后看length属性值为多少,去选取从'0'到length-1的数字属性的值去变成一个数组。说个不常见的现象:两个参数length和如果是-1这种无意义的值,转变后length:NaN,属性也不对
说完了$.makeArray()的用法,但是里面传了两个参数,这比较不常见但是,可以类比$.merge猜一下:就是返回的结果不是数组了,而是一个有length属性的伪数组(对象)。
console.log($.makeArray({'0':1,'1':2,'a':3,length:2},{length:1})); //{1: 1, 2: 2, length: 3}
console.log($.makeArray( {'0':1 ,'1':2,'a':3,length:2},{'0':5,'1':8,'2':9,'a':'哈哈',length:2} ));//{0: 5, 1: 8, 2: 1, 3: 2, a: "哈哈", length: 4}
总结一下:$.makeArray的第二个参数必须有length属性(默认是数组),第二个参数如果写了对象,还发生了合并操作就是把第一个参数的数字属性值添加(不是覆盖)到第二个参数对象里,length相加,如果两个参数有重名,看第二个参数的length,如果为0,第一个参数为准,如果不为0,以第二参数为准,并且第一个参数添加进来往后排(特别注意:往后排不是简单地+1,而是看合并后的总length,去添加属性数字值),第二个参数的非数字属性不要动。
简单来说:与$.merge()的区别除了参数要求,合并的时候$.merge()会根据本身length值选取出数字属性的部分,而$.makeArray()则会保留所有属性。
return jQuery.makeArray(selector, this);
再来看一下,首先这句代码是返回init : function(){}里面的,也就是说默认返回的是这么一个对象,特征是有数字属性,有length属性,还有一些其他属性(前面有context)。
其实在各个if判断里有些return了,所以这里只是告诉那些没return的,执行这个return,其实就是最后的情况去return,一个意思
回顾一下到底init:function(){}干了什么事情:返回了一个this,这个this对象属性里有原生节点,还有length属性。
// Start with an empty selector selector: '', //其实就是给selector赋一个初值'' // The default length of a jQuery object is 0 length: 0, //其实就是给length赋一个初值0 toArray: function() { return core_slice.call(this); //core_slice是一个前面定义的方法[].slice,通过借用 相当于把this当成一个数组去掉用,所以this必须是一个有length的对象才行 },
$(选择器).toArray()方法:jQuery对象转数组,与$.makeArray()的区别在于$(选择器).toArray()只能把jQuery对象转成数组,后者只要是对象都能转(而且是$去调用),转的方式上文中具体讲了一些。其实toArray()是为了以后的封装方法做准备的,单独的使用不常用,所以别觉得他的功能其他方法也有就觉得多余,其实其他方法在封装的时候需要用到这个方法。从另一个角度看,下文封装了$(选择器).get()功能更强大,但是写的更少,体现了他的宗旨:''write Less,Do More''
init方法返回的jQuery对象可以用$.toArray()去转成数组。
// Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function(num) { return num == null ? // Return a 'clean' array this.toArray() : // Return just the object num < 0 ? this[this.length + num] : this[num]; },
$(选择器).get()注意这些方法都是定义在init里的所以使用他们应该是一个$(选择器)的形式,而不是一个$.的形式,$.的形式不是写在init里的
$('div').get() => 相当于$('div').toArray() ; $('div').get(0) <=> $('div').toArray()[0] ;$('div').get(n) <=> $('div').toArray()[n]( n > 0 ) ; $('div').get(n) <=> $('div').toArray()[$('div').toArray().length - n] (n < 0 也就是倒着数,不过倒着数最后一项是 -1 ,因为 -0 就是0 是第一项)
其实$('div').get()实现方法用了三元运算符的嵌套,把代码拉成一行num == null? this.toArray(): num < 0 ? this[this.length + num] : this[num]; 首先分析一下首选算num == null(调皮了,其实这里写undefined也是可以的,但是undefined == null) ? 没有传参走 this.toArray() 传参了走 num < 0 ? this[this.length + num] : this[num];
在传参的情况下判断num是不是负数:是就取第this.lenth + num 下标的值,不是负数(正数 和 其他类型)取num的值,当然了其他类型this中没有num这个属性,那就返回undefined,
其实在我们看了源码以后其实不难看出,就算不是数字参数,只要是this里面有的属性名传进去就是取到了this[参数名],但是这无任何意义,因为直接this[参数名]不就好了?