定义两个函数
html
<body>
<ul>
<li id="item1">选项1</li>
<li id="item2">选项1</li>
<li id="item3">选项1</li>
<li id="item4">选项1</li>
<li id="item5">选项1</li>
</ul>
</body>
function getsiblings (node) {
var allChildren = node.parendNode.children
var array = {length: 0}
for (let i=0; i < allChildren.length; i++) {
if (allChildren[i] !== node) { // 此处有一个点,就是少用 == 和!=
array[length] = allChildren[i]
array.length += 1
}
}
return array
}
function addClass (node, classes) {
for(let key in classes) {
let value = classes[key]
let mothedName = value ? 'add' : 'remove'
node.classList[mothedName](key)
}
}
getSiblings(item3)
addClass(item3, {'a': true, 'b' : false})
此时上面已经有了两个可以使用的函数,分别有不同的用途。当你的函数库发展到一定的数量时,我们需要给他们一个名字,把他们统一起来。这时候出现的命名空间的概念:它表示着一个标识符(identifier)的可见范围。一个标识符可在多个名字空间中定义,它在不同名字空间中的含义是互不相干的。这样,在一个新的名字空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其他名字空间中。
命名空间就可以让相同的变量名不冲突。我们不希望函数库的函数命名和用户的其他变量冲突。
使用命名空间可以让人知道你的库叫什么,而且不会覆盖用户的同名变量
window.myDom = {}
myDom.getSiblings = function (node) {
var allChildren = node.parendNode.children
var array = {length: 0}
for (let i=0; i < allChildren.length; i++) {
if (allChildren[i] !== node) { // 此处有一个点,就是少用 == 和!=
array[length] = allChildren[i]
array.length += 1
}
}
return array
}
myDom.addClass() = function (node, classes) {
for(let key in classes) {
let value = classes[key]
let mothedName = value ? 'add' : 'remove'
node.classList[mothedName](key)
}
}
myDom.getSiblings(item3)
myDom.addClass(item3, {'a': true, 'b': false})
上面的代码还有一个问题,就是每次都要输入myDom。我现在想直接
item3.getSiblings()
。
Node.prototype.getSiblings = function () {
var allChildren = this.parendNode.children
var array = {length: 0}
for (let i=0; i < allChildren.length; i++) {
if (allChildren[i] !== this) { // 此处有一个点,就是少用 == 和!=
array[length] = allChildren[i]
array.length += 1
}
}
return array
}
item3.getSiblings() // 此时就可以这样执行
Node.prototype.addClass = function (classes) {
for(let key in classes) {
let value = classes[key]
let mothedName = value ? 'add' : 'remove'
this.classList[mothedName](key)
}
}
item3.addClass({a: true, b: false}) // 不知道this请使用call()方法
上面的代码需要说明的是,item3是Element构造函数的实例,Element继承Node。所以在Node.prototype上的方法,item3可以直接调用到(通过原型链)。
还有一个this的问题。上面的item3.getSiblings()
调用方式,很多人并不知道为什么this是item3。
所以我们每次在调用函数时应该使用call()方法调用
call()方法的第一个参数就是this值。 请使用call()方法调用函数
上面的代码还是有问题的,我们直接在prototype中添加方法,用户可能会写相同名字的变量到prototype中,导致覆盖。所以这种也并不是好办法。
window.JQuery = function (nodeOrSelector) {
let node
if (typeof nodeOrSelector === "string") {
document.querySelector(nodeOrSelector)
} else {
node = nodeOrSelector
}
return {
getSiblings: function () {
var allChildren = this.parendNode.children
var array = {length: 0}
for (let i=0; i < allChildren.length; i++) {
if (allChildren[i] !== node) {
array[length] = allChildren[i]
array.length += 1
}
}
return array
}
addClass: function (classes) {
for(let key in classes) {
let value = classes[key]
let mothedName = value ? 'add' : 'remove'
node.classList[mothedName](key)
}
}
}
}
JQuery('#item3').getSiblings()
JQuery('#item3').addClass({a: true, b: false})
升级版
window.JQuery = function (nodeOrSelector) {
let nodes = {}
if (typeof nodeOrSelector === 'string') {
let temp = document.querySelectorAll(nodeOrSeletor) // 这里也是伪数组,但是原型链上会指向Node
for (let i = 0; i < temp.length; i++) { // 此时是为了得到纯净的伪数组,即直接继承自Object
nodes[i] = temp[i]
}
nodes.length = temp.length
} else if (nodeOrSelector intanceof Node) {
nodes = {
0: nodeOrSelector,
length: 1
}
}
nodes.addClass = function (classes) {
for (let key in classes) {
let value = classes[key]
let methodName = value ? 'add' : 'remove'
for (let i = 0; i < nodes.length; i++) {
nodes[i].classList[methodName](key)
}
}
}
nodes.text = function (text) {
if (text === undefined) { // 判断是否传值,没有传值表示想获取标签内的值。
let texts = []
for (let i = 0; i < nodes.length; i++) {
texts.push(nodes[i].textContent)
}
return texts
} else { // 表示设置标签内的值
for (let i = 0; i < nodes.length; i++) {
nodes[i].textContent = text
}
}
}
return nodes
}
JQuery('ul > li').addClass({blue: true})
JQuery('ul > li').text('hi')
封装一个ajax
window.JQuery.ajax = function ({url,method,body}) {
return new Promise((resolve, reject) => {
let request = new XMLHttpRequest()
request.open(method, url)
request.onreadystatechange = function () {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
resolve.call(undefined, 'success')
}else if (request.status >= 400) {
reject.call(undefined, 'fail')
}
}
}
request.send(body)
})
}
window.JQuery.ajax({
url: '/xxx',
method: 'get'
}).then(
(text) => {console.log(text)},
(text) => {console.log(text)}
)