首先我们来看下封装函数的两种方式
function getSiblings(node){} //直接通过function关键字封装函数
var dom = {} //创建一个命名空间把函数放入命名空间
dom.getSiblings(node)
dom.addClass(node, {a: true, b: false})
上面两种方法封装的函数的node如果想放到前面
node.getSiblings()
node.addClass()
如上代码所示这样调用的话该如何做呢
- 方法一:扩展 Node 接口(即公有属性/原型)
直接在 Node.prototype 上加函数 - 方法二:新的接口 如下代码所示
window.jQuery = function(nodeOrSelector){
let nodes={}
if(typeof nodeOrSelectoe==='string'){
let temp=document.querySelectorAll(nodeOrSelector)
for(let i=0;i<temp.length;i++){
nodes[i]=temp[i]
}
nodes.length=temp.length
}else{
nodes={
0: nodeOrSelector,
length: 1
}
}
nodes.addClass=function(classes){
classes.forEach((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].textContent=text
}
}
return nodes
}
window.$ = jQuery
var $div = $('div')
$div.addClass('red')
$div.setText('hi')
接下来通过上面代码讲解下jQuery是如何实现的
- 首先在window这个对象下创建一个属性jQuery,它的值是一个函数,函数的参数是一个变量,函数的返回值是一个对象。
- 我们先初始化一个对象用来存放我们的函数。
- 通过一个if判断这个变量的值是否为字符串,如果是字符串我们就用DOM的API querySelectorAll方法去寻找匹配的元素节点并且用一个变量存储起来,由于返回的是一个Node集合对象,他的原型指向了Node.prototype,我们并不需要这个原型上的方法,所以我们把这个集合遍历一遍取出存放到我们初始化的对象上,并且把length属性也赋值过去,这样我们的对象的原型就直接指向了Object.prototype。这样就会干净很多,我们的原型链上没有那些我们不需要的东西。
- 如果值不是字符串,那么传进来的就是一个元素节点对象,我们只需要把它放到我们的初始化对象下标为0的地方,并且length属性的值为1。
- 然后我们自定义的函数放在这个对象里面,这样做的好处是即使外面有同名函数也不会产生覆盖,这种做法叫做无侵入。
- 在最后记得把这个对象作为返回值传出去。
这样我们就可以通过var $div = $('div')去把我们要找的元素节点封装成对象的属性然后再返回这个对象。
$div.addClass('red') 我们就可以这样去调用对象里面的方法了。
jQuery就是这样把一些难用难记DOM API封装成新的好用的API的。当然jQuery并不是这么简单,只是讲解下如何像jQuery那样去封装函数。