如何實現乙個簡化版的 jQuery

2021-09-07 09:14:56 字數 2931 閱讀 8827

對於操作dom來說,jquery是非常方便的乙個庫,雖然如今隨著react,vue之類框架的流行,jquery用得越來越少了,但是其中很多思想還是非常值得我們學習的,這篇文章將介紹如何從零開始實現乙個簡化版jquery

在這裡,我把這個庫命名為 clus(class 的諧音),下面以$符號代替。

首先需要宣告乙個建構函式並做一些初始化操作:

function $(selector) 

$.fn = $.prototype = ;

可以看到,該建構函式返回乙個$.fn.init的例項,這樣做的好處就是在使用的時候不要每次都new乙個建構函式就可以建立乙個新的例項了,可以看出來,整個核心都在init函式上了:

function init(selector)  else if (elementtypes.indexof(selector.nodetype) !== -1 || selector === window)  else if (selectortype === 'function')  else if (selectortype === 'array')  else if (selectortype === 'object')  else if (selectortype === 'string')  else 

}dom = dom || ;

$.extend(dom, $.fn);

dom.selector = selector;

return dom;

}

可以很清楚的看到,根據傳入的引數型別的不同進行一些不同的操作,比如傳入的是函式的話,則該函式裡的操作的都是dom ready之後的操作了;再比如傳入的是字串的話,並且如果是標籤的話,則會把這段標籤字串解析成dom fragment,如果是普通字串,則會呼叫document.queryselectorall()方法來查詢 dom。

相信大家都能很容易的看明白上面的**,不過有一點值得一提的是$.extend(dom, $.fn);這段**,其含義是把例項上的所有方法都新增到dom這個陣列物件中,這樣做的目的就是為了可以直接鏈式呼叫某個例項的方法,比如$('.clus').addclass('hello'),這個addclass()方法就是在$.fn上實現的。因此所有在$.fn實現的方法都可以通過$(selector).method()這種方式來呼叫了。

至於extend()方法我認為是除了init()方法以外,整個庫中最核心的乙個方法了,**如下:

export default function extend() ,

i = 1,

length = arguments.length,

deep = false;

if (typeof target === 'boolean') ;

i++;

}if (typeof target !== 'object' && $.type(target) !== 'function') ;

}if (i === length)

for (; i < length; i++)

// deep clone

if (deep && copy && ($.isplainobject(copy) || (copyisarray = array.isarray(copy)))) else ;

}target[name] = extend(deep, clone, copy);

} else if (copy !== undefined) }}

}return target;

}

可以看到,和jquery的實現一毛一樣,沒錯就是從那兒 copy 過來的當然一樣。

下面以addclass()方法為例介紹如何操作 dom 的:

function addclass(cls)  `.replace(rclass, ' ');

if (cur) `) == -1)

finalvalue = $.trim(cur);

if ( curvalue !== finalvalue ) }}

}}

return this;

}$.fn.addclass = addclass;

值得一提的就是在例項方法中,this關鍵字可以訪問到根據選擇器所查詢到的所有元素的集合,在這裡是通過while迴圈來對每個元素進行操作。要實現類似$(selector).addclass().removeclass()這樣的鏈式操作,只需要在每個例項方法中返回乙個this即可。要實現其他例項方法比如hasclass()之類的也是類似的方法。

其實每個例項方法都是通過this關鍵字來獲取查詢到的元素,然後遍歷這些元素來針對每個元素進行具體的操作,在舉乙個栗子:

let el, i = 0,

fregmentcollection = $.parsehtml(domstring),

while((el = this[i++])) );

}return this;}

其他例項方法也是通過類似的方式實現的,這裡就不一一細說了,想更詳細的檢視其他方法的實現可以直接到 clus 中檢視原始碼。

手寫乙個簡化版Tomcat

我們啟動tomcat時雙擊的startup.bat檔案的主要作用是找到catalina.bat,並且把引數傳遞給它,而catalina.bat中有這樣一段話 bootstrap.class是整個tomcat 的入口,我們在tomcat原始碼裡找到這個類,其中就有我們經常使用的main方法 這個類有兩...

Redux自己手寫乙個簡化版全面的redux

import react from react const renderscreen screen const renderbutton button 1.全域性渲染方法 渲染螢幕 renderscreen state.screen 渲染按鈕 renderbutton state.button 2....

分享自己寫的乙個簡化版LOG輸出巨集

extern int verbose define dbg xlog 4,dbg va args define info xlog 3,inf va args define wrn xlog 2,wrn va args define err xlog 1,err va args define out...