jQuery 是 JavaScript 中使用非常广泛的库,究其原因的话,一方面是它确实方便,另一方面是对于程序员来说,浏览器提供的 API 太垃圾了 ……
比如,浏览器没有提供获取同级兄弟节点的API,也没有同时给多个节点输入内容的 API。
今天,我们来模拟一下 jQuery 的原理,给自己定义一些浏览器“欠缺”的 API。
jQuery 是什么形式呢?
jQuery(a).addClass();
它会先选择,然后就可以调用 jQuery 的各种 API 来操作这些被选择的对象了。
于是,首先,我们生成一个 local 作用域来存放我们将要设计的各种 API,这样我们完全不用顾虑会影响到全局变量。
let myDomWithApi = function () {
let nodes = {};
return nodes;
}
上面的代码中,我们创建了一个函数,最终返回一个对象,我们希望我们想要处理的节点对象以及自定义的 API 就存在于这个对象中。
于是,我们开始选择:
let myDomWithApi = function(nodeOrSelector) {
let nodes = {};
let temp = document.querySelectorAll(nodeOrSelector); //用原生 API 获取节点
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 = {};
// 省略;
// 比如,我们想同时给所有已选择的节点加上 class ...
nodes.addClass = function(value) {
for (let i = 0; i < nodes.length; i++){
nodes[i].classList.add(value);
};
};
// 同时修改所有已选节点的文本:
nodes.setText = function(text) {
for (let i = 0; i < nodes.length; i++ ) {
nodes[i].innerHTML = text;
};
};
// 我们想要找一个节点的同级兄弟:
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){
// 把除了自己以外的节点加到新的对象中;
array[array.length] = allChildren[i];
array.length++;
};
};
return array;
};
return nodes;
}
完成!这样我们就可以快乐地使用自己的 API 了:
let div = myDomWithApi("div");
div.addClass = "xxx" // Work!
//如果,我们把原来的函数名改为:myDomWithApi → jQuery
//那么就可以生成一个很像 jQuery 的东西了
let jQuery = ……
jQuery("div").addClass = "xxx"
//如果再设置个$,那就更像了 ……
window.$ = jQuery;
$("div").addClass = "xxx" // 一样效果!
在写上一篇文章的时候,我还不太清楚闭包的作用,不过,今天就碰上了,这就是闭包,内层作用域的变量与外层链接了。
window.nodes // → Uncaught ReferenceError: nodes is not defined
网友评论