上一遍文章我们介绍了jquery链式调用及class、id选择器的实现原理,接下来丰富下源码以及介绍下get和eq方法的源码实现!

html代码:

<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>

$(".box").get() : 这个方法是选择出相对应的dom元素,返回的是一个或多个原生dom元素;分以下几种情况:

     1、 get ( )  括号中正常传递参数时,如 0、1 、2、3 ····时,返回的是索引对应的元素;

      2、传递参数为负数的时,如 -1、-2、-3 ··· 时,返回的是 【数组长度(length)+ 参数】 所对应的元素 ;

      3、没参数(不传递参数)时,返回的是选中的所有元素,是一个普通数组。

源码实现:

// get方法源码实现
jQuery.prototype.get = function(num){//num是参数(传递的索引)
// +++++++++++++++写法一:
if(num == null){//没传参数的情况
//因为类数组中没有slice这个方法,所以我们用call借用数组中slice这个方法,来把类数组的元素截取出来,把类数组变成数组,【注意】对于类数组转化为数组通常用数组slice这个方法,空截取,可转化为普通数组
return Array.prototype.slice.call(this,0)// === [].slice.call(this,0)
}
if(num >= 0){//正常数字
return this[num]
}else{
return this[this.length + num]//这种情况是num为负数的时候,大家可以自己实践下
}
};

还有一种写法是:

jQuery.prototype.get = function(num){
// +++++++++++++++写法二:
return num != null ? (num >= 0 ? this[num] : this[this.length + num]) : [].slice.call(this,0);

};

$(".box").eq() : 这个方法也是选择出相对应的dom元素,不过返回的是一个jq对象;括号中的参数也分以下几种情况:

     1、 eq ( )  括号中正常传递参数时,如 0、1 、2、3 ····时,返回的是索引对应的元素;

      2、传递参数为负数的时,如 -1、-2、-3 ··· 时,返回的是 【数组长度(length)+ 参数】 所对应的元素 ;

      3、没参数(不传递参数)时,返回的是空对象,length为0 。

源码实现:

// eq方法源码实现
jQuery.prototype.eq = function(num){
// 下边选择出来的跟get源码一样,是一个原生的dom,我们返回的是一个jq对象才行,所以,要完善下参数传递原生dom的情况了
var dom = num != null ? (num >= 0 ? this[num] : this[this.length + num]) : null;//如果没传递参数,则直接返回空对象
return jQuery(dom)//返回的是一个jq对象
};

因为上边的源码实现跟get方法差不多,只是返回的要是一个jq对象,所以我们要考虑当传递原生dom的时候,参数要怎样判断呢?我们接着上一遍文章源码优化:

(function () {
function jQuery(selector){
return new jQuery.prototype.init(selector);
}
//参数判断
jQuery.prototype.init = function(selector){
// this = {}
this.length = 0;
//判断selector是否为空(null或者undefined,null==undefined为true)
if(selector == null){
return this;//selector这个参数为空时,直接返回构造出来的对象,也是就是this
}
//当传递原生dom对象时,它是没有indexOf这个字符串方法的,所以我们前面在加一层条件,判断selector是否是一个字符串形式的
if ( typeof selector == "string" && selector.indexOf(".") != -1 ){
var dom = document.getElementsByClassName(selector.slice(1));
}else if ( typeof selector == "string" && selector.indexOf("#") != -1 ){
var dom = document.getElementById(selector.slice(1));
}
//当selector参数为原生dom的时候
if(selector instanceof Element){//用instanceof来判断selector构造函数是否是Element,返回的是布尔值
this[0] = selector;
this,length ++ ;
}
if ( dom.length == undefined ) {
this[0] = dom;
this.length ++ ;
}else{
for ( var i = 0 ; i < dom.length ; i ++ ) {
this[i] = dom[i];
this.length ++ ;
}
}
};
//链式调用
jQuery.prototype.css = function(config){
for( var i = 0 ; i < this.length ; i ++ ){
for( attr in config ){//循坏config对象
this[i].style[attr] = config[attr];
}
}
return this;
}
jQuery.prototype.init.prototype = jQuery.prototype;
window.$ = window.jQuery = jQuery;
})()

细心的人会发现,判断是否是原生dom条件里边的代码跟下边条件里边的代码重复了,我们可以把判断是否是原生dom这个条件写在下边的条件里,2个条件中间加一个或( || )运算符,简化了多余的代码,如下:

if ( selector instanceof Element || dom.length == undefined ) {
this[0] = dom || selector;
this.length ++ ;
}else{
for ( var i = 0 ; i < dom.length ; i ++ ) {
this[i] = dom[i];
this.length ++ ;
}
}

以上就是get和eq方法的源码实现,有不懂的小伙伴,欢迎留言!