接昨天的jQuery源码研究:为jQ对象扩展的一些工具方法(上),今天继续。
6、trim
方法:删除字符串开始与结尾的空格,来看下方法实现:
jQuery.extend({
trim: function(text){
return text == null ?
"":
(text + "").replace(rtrim, "");
}
})
解释:如果参数text
值为null
或者undefined
,则返回空字符串;否则就通过replace()
方法传入对应正则进行匹配替换。这里rtrim
参数变量是在源码开头就定义好的的一个正则表达式变量rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
。
这个方法的return
表达式有两个小知识点:
undefined == null
为真text+""
这里是用到js中的字符串转义,确保始终是对字符串在进行replace
操作7、makeArray()
方法:将一个类数组转化成真正的数组对象。类数组虽然具有许多数组的属性,比如length
,[]
数组访问运算符等,但是却没有从数组的原型对象上继承下来的内置方法。
jQuery.extend({
makeArray: function( arr, results ) {
var ret = results || [];
if ( arr != null ) {
if ( isArrayLike( Object( arr ) ) ) {
jQuery.merge( ret,
typeof arr === "string" ?
[ arr ] : arr
);
} else {
push.call( ret, arr );
}
}
return ret;
},
})
解释:方法里的results
参数,在代码中有注意:仅供内部使用。意为只有在源码内部调用这个makeArray
方法时,才会传入results
参数,而在外部调用这个静态方法makeArray
时,都只会传入一个参数,即要转为数组的参数arr
。当arr
参数不为null
时,进入方法处理的逻辑判断,内部将参数arr
的数据类型分为两种情况:
length
属性的对象,这里就调用jQuery.merge
方法进行处理,这个方法等会在下面详讲;length
属性的有键值对的对象,此时通过call
调用原生数组的push()
方法来将参数对象arr
传入方法开始就创建好的空数组中,生成以对象参数为元素的数组。8、inArray()
方法,作用其实就是检测数组中是否存在某个元素,如存在则返回元素对应的索引,如不存在,则返回-1
。这个方法其实就是对js原生数组indexOf
方法的使用封装,看源码:
jQuery.extend({
inArray: function(elem, arr, i){
return arr == null ? -1 : indexOf.call(arr, elem, i)
}
})
解释:很简单的一行代码,通过三目运算符,先对传入数组arr
进行null
判断,如为空直接返回-1
,告诉开发者,这货不存在,因为你连数组都没告诉我,我怎么知道你有没存在的,丢你一脸的-1;如果arr
源数组传入了,那么就通过call
调用早前定义的好的indexOf
方法,来对数组arr
进行值elem
存在检测。这里需要复习下原生的indexOf
方法:其可返回某个指定的元素首次出现的位置,方法参数1必传需检索的元素值,参数2选传整数参数,以规定开始检索的位置。
9、merge()
方法:合并两个数组内容到第一个数组。这个方法接收两个数组参数first
和second
。first
数组是用于合并的数组,方法最后返回的first
数组会包含合并后的第二个数组的内容,而second
数组内容在合并后不会被修改。具体实现看源码:
jQuery.extend({
merge: function(first, second){
var len = +second.length,
j = 0,
i = first.length;
for(; j<len; j++){
first[i++] = second[j];
}
first.length = i;
return first;
}
})
解释:对second
数组进行遍历,将该数组中的元素接到first
数组的后面,形成新的数组,并手动更新first
数组的长度。这里注意,由于数组是引用数据类型,所以first
数组内容更新了。
10、grep()
方法,使用指定的回调函数来过滤数组中的元素,并返回过滤后的数组。
jQuery.extend({
grep: function(elems, callback, invert){
var callbackInverse,
matches = [],
i = 0,
length = elems.length,
callbackExpect = !invert;
for(; i<length; i++){
callbackInverse = !callback( elems[i], i );
if( callbackInverse !== callbackExpect ){
matches.push( elems[i] );
}
}
return matches;
}
})
解释:在方法的for
循环中,只有通过检测函数callback
筛选的项会被保存下来并存进数组matches
中,这不会影响到原数组。看callback
函数的传入参数可知,外面指定的筛选函数需要传入两个参数,参数1是数组元素值,参数2是元素索引。另外方法的参数3invert
其实是个布尔值,默认为false
,其作用在于是否需要反转筛选项。
11、map()
方法,遍历数组中的每个元素或者对象中的每个属性,并将处理后的结果push
进新的数组并返回。
jQuery.extedn({
map: function(elems, call, arg){
var length, value,
i = 0,
ret = [];
if( isArrayLike(elems) ){ //类数组对象
length = elems.length;
for( ; i<length; i++ ){
value = callback( elems[i], i, arg );
if( value != null ){
ret.push( value );
}
}
}else { //普通对象
for( i in elems ){
value = callback( elems[i], i, arg );
if( value != null ){
ret.push( value );
}
}
}
return concat.apply( [], ret );
}
})
好了,关于jQuery.extend()
扩展出来的一些工具方法,就到这里。在上面讲的方法实现中,关于call
和apply
的使用是异常频繁的,它也是js比较诡异却又神奇的一个特点,需要真正弄清哦。