jQuery 是 JavaScript 中使用非常廣泛的庫,究其原因的話,一方面是它確實(shí)方便,另一方面是對于程序員來說,瀏覽器提供的 API 太垃圾了 ……
比如,瀏覽器沒有提供獲取同級兄弟節(jié)點(diǎn)的API,也沒有同時(shí)給多個(gè)節(jié)點(diǎn)輸入內(nèi)容的 API。
今天,我們來模擬一下 jQuery 的原理,給自己定義一些瀏覽器“欠缺”的 API。
jQuery 是什么形式呢?
jQuery(a).addClass();
它會(huì)先選擇,然后就可以調(diào)用 jQuery 的各種 API 來操作這些被選擇的對象了。
于是,首先,我們生成一個(gè) local 作用域來存放我們將要設(shè)計(jì)的各種 API,這樣我們完全不用顧慮會(huì)影響到全局變量。
let myDomWithApi = function () {
let nodes = {};
return nodes;
}
上面的代碼中,我們創(chuàng)建了一個(gè)函數(shù),最終返回一個(gè)對象,我們希望我們想要處理的節(jié)點(diǎn)對象以及自定義的 API 就存在于這個(gè)對象中。
于是,我們開始選擇:
let myDomWithApi = function(nodeOrSelector) {
let nodes = {};
let temp = document.querySelectorAll(nodeOrSelector); //用原生 API 獲取節(jié)點(diǎn)
if (typeof nodeOrSelector === "string") {
for (let i = 0; i < temp.length; i++) {
nodes[i] = temp[i];
};
nodes.length = temp.length;
} else {
nodes = {
//如果輸入是 node,直接拿來用;
0: nodeOrSelector,
length: 1
};
};
return nodes;
}
在接下來,我們就可以開始定義自己的 API 了:
let myDomWithApi = function (nodeOrSelector) {
let nodes = {};
// 省略;
// 比如,我們想同時(shí)給所有已選擇的節(jié)點(diǎn)加上 class ...
nodes.addClass = function(value) {
for (let i = 0; i < nodes.length; i++){
nodes[i].classList.add(value);
};
};
// 同時(shí)修改所有已選節(jié)點(diǎn)的文本:
nodes.setText = function(text) {
for (let i = 0; i < nodes.length; i++ ) {
nodes[i].innerHTML = text;
};
};
// 我們想要找一個(gè)節(jié)點(diǎn)的同級兄弟:
nodes.getSiblings = function (node) {
let allChildren = node.parentNode.children;
let array = {length: 0};
for (let i = 0; i < allChildren.length; i++) {
if (allChildren[i] !== node){
// 把除了自己以外的節(jié)點(diǎn)加到新的對象中;
array[array.length] = allChildren[i];
array.length++;
};
};
return array;
};
return nodes;
}
完成!這樣我們就可以快樂地使用自己的 API 了:
let div = myDomWithApi("div");
div.addClass = "xxx" // Work!
//如果,我們把原來的函數(shù)名改為:myDomWithApi → jQuery
//那么就可以生成一個(gè)很像 jQuery 的東西了
let jQuery = ……
jQuery("div").addClass = "xxx"
//如果再設(shè)置個(gè)$,那就更像了 ……
window.$ = jQuery;
$("div").addClass = "xxx" // 一樣效果!
在寫上一篇文章的時(shí)候,我還不太清楚閉包的作用,不過,今天就碰上了,這就是閉包,內(nèi)層作用域的變量與外層鏈接了。
window.nodes // → Uncaught ReferenceError: nodes is not defined