首先要理解,JavaScript的語法是需要引擎來實現(xiàn)的.引擎是用其他語言寫的(一般是c或者java).因為JavaScript語言在瀏覽器中已經(jīng)實現(xiàn)了.所以可以用JavaScript寫API; API就是給別人用的代碼,可以說是工具,JavaScript實現(xiàn)這種工具一般就是用函數(shù)(可以執(zhí)行代碼的對象就是函數(shù),對象就是基本類型的集合,因為數(shù)據(jù)結(jié)構(gòu)不同,具體區(qū)分了單純對象+函數(shù)+數(shù)組)
這堂課是要通過實現(xiàn)類似jQuery的函數(shù)庫,來體會jQuery究竟是什么東西.首先就來,封裝一個函數(shù)體驗一下
- 通常來說,使用nodeType屬性確定一個節(jié)點的類型,比較方便
document.querySelector('a').nodeType === 1 - Node.nodeValue屬性返回一個字符串,表示當(dāng)前節(jié)點本身的文本值,該屬性可讀寫。
- Node.textContent屬性返回當(dāng)前節(jié)點和它的所有后代節(jié)點的文本內(nèi)容。textContent屬性自動忽略當(dāng)前節(jié)點內(nèi)部的HTML標(biāo)簽,返回所有文本內(nèi)容。
- 屬性和方法的區(qū)別在于,函數(shù)屬性就是方法,因為函數(shù)可以返回一個東西.
- 阮一峰,jquery設(shè)計思想
- 庫是什么呢?庫是特定種類的API //全球瀏覽器使用量登錄builtwith查看
自己寫,就懂什么是jQuery了//代碼如下
var allChild = itme3.parentNode.children
var array= {length:0}
for(let i=0;i<allchild.length,i++){
if (allChild[i]!==item3){
array[array.length]=allChild[i]
array.length+=1
}
}
這是實現(xiàn)一個偽數(shù)組的代碼.偽數(shù)組就是hash;
- 然后給他封裝,也就是寫個函數(shù)取個名字唄~~~~~
具體實現(xiàn)獲取一個元素所有兄弟的代碼如下::::::::
function 獲取所有兄弟(node){
var allChild =node.parentNode.children
var array= {length:0}
for(let i=0;i<allchild.length,i++){
if (allChild[i]!==node){
array[array.length]=allChild[i]
array.length+=1
}
return array
}
}// 這樣就通過代碼封裝出一個'獲取所有兄弟'的API了
現(xiàn)在來寫第二個,添加多個class的API
var classes = { 'a':true,'b':false,'c':true}
for ( let key in classes){
var value = classes[key]
if ( value) {
item3.classList.add(key)
} else{
item3.classList.remove(key)
}
}
//// 我們來封裝一下,把他放進(jìn)一個函數(shù)里面,讓別人使用// 這個過程中就要考慮到多個問題了,首先要處理的對象要被人給,所以留出參數(shù)給別人使用,也就意味著不能寫死代碼.
function addClass(node,classes){
for(let key in classes){
var value = classes[key]
if(value){
node.classList.add(key)
}else{
node.classList.remove(key)
}
}
}
寫了兩個API 那么就來優(yōu)化一下,體驗整個過程
代碼優(yōu)化守則第一個: 有類似的代碼就存在優(yōu)化的可能//我們來優(yōu)化上面的代碼
function addClass(node,classes){
for( let key in classes){
var value = classes[key]
var methodName = value ? 'add':'remove'
node.calssListmethodName
}
}// 這不單可以加calss,還可以減class要是簡單實現(xiàn)加,那么使用以下代碼,更簡單
function addClass(node,classes){
classes.forEach((value)=>node.classList.add(value))
}
接下來講命名空間//程序員覺得一個東西好就會娶個專業(yè)名詞~~~因為代碼是開源的,你可以寫組件,別人也寫了組件,那么在使用的時候,你要區(qū)分開來,當(dāng)然最直觀的是靠名字來區(qū)分啦~~~~所謂的命名空間,一個是彰顯自己的牛逼,還有就是區(qū)分不同人寫的不同組件,模塊
//真實的意義:
- 如果沒有命名空間,別人就不知道你的庫叫什么
- 如果沒有命名空間,你會不知不覺把所有全局變量覆蓋了,比如說,你要在一家公司做前端,之前的員工肯定寫了屬于他自己的庫,他的函數(shù)庫有很多的不知名字的函數(shù)可以調(diào)用,可是不知道他都寫了哪些API,就算有名字你也記不全,那么工作的時候,你覺得自己的API好用,又寫了,因為功能相似,名字恰巧又一樣了.完了~~~~你的API是不是把別人的給覆蓋了? 那么之前經(jīng)他手的代碼是不是都出問題了,因為通用的函數(shù)名,讓你給覆蓋了.
Windows.jasonDom = {}
jasonDom. getSiblings = getSliblings
原型鏈其實就是公有屬性鏈:Element_proto_ === Node.prototype(//這就是公有屬性)
那么久出現(xiàn)一個問題:A 好用還是B好用呢?當(dāng)然是B好用啊!!! 如何實現(xiàn)呢?有兩個辦法,第一個是修改原型代碼,也就是修改原型鏈的頂端代碼; 另外一個就是用this
調(diào)用函數(shù)一般就是簡單加個(),就可以了,這種方式的this是隱式的,誰調(diào)用就是this;另外一種就是用call()來調(diào)用函數(shù),這種是明確指定this的.
item3.getSiblings.call(item3)// 等價于item3.getSiblings
this;使用閉包的目的——隱藏變量;所以函數(shù)套函數(shù)只是為了造出一個局部變量,跟閉包無關(guān)。
關(guān)于閉包的謠言
閉包會造成內(nèi)存泄露?
錯。
說這話的人根本不知道什么是內(nèi)存泄露。內(nèi)存泄露是指你用不到(訪問不到)的變量,依然占居著內(nèi)存空間,不能被再次利用起來。
閉包里面的變量明明就是我們需要的變量(lives),憑什么說是內(nèi)存泄露?
這個謠言是如何來的?
因為 IE。IE 有 bug,IE 在我們使用完閉包之后,依然回收不了閉包里面引用的變量。
這是 IE 的問題,不是閉包的問題。參見司徒正美的這篇文章。
1.可以訪問其他函數(shù)內(nèi)變量的函數(shù),叫做閉包。
2.閉包可以用來保存一個需要持久保存的變量,可以模擬命名空間。
this詳細(xì)文章請看 方老師的文章
總結(jié):
- this 就是你 call 一個函數(shù)時,傳入的 context。
- 如果你的函數(shù)調(diào)用形式不是 call 形式,請按照「轉(zhuǎn)換代碼」將其轉(zhuǎn)換為 call 形式。以后你遇到所有跟 this 有關(guān)的筆試題,都不會有疑問了。
上面對this的闡述是不完整的,因為根據(jù)上面所有,那么調(diào)用API的時候,由于API是瀏覽器預(yù)先封裝好的,源代碼也看不見,鬼知道誰調(diào)用了函數(shù)~~~~這也是個大問題
- 總結(jié)一下如何確定 this 是值
- 看源碼中對應(yīng)的函數(shù)是怎么被 call 的(這是最靠譜的辦法)
- 看文檔
- console.log(this)
- 不要瞎猜,你猜不到的
前面提到可以修改Node的原型屬性,來實現(xiàn)新的方法屬性,但是這種做法是很不規(guī)范的,因為要是有人已經(jīng)改寫了同名函數(shù),你又去改寫,是不是把他給覆蓋了,這是很不負(fù)責(zé)任的做法.所以我們只能選擇第二種方法,重新寫一個Node2屬性//代碼如下
window.Node2 = function (node){
return {
getSilbings:function(){},
addClass:function(){}
}
}
var node2 Node2(item3)
node2.getSiblings()
node2.addClass()
也就是說,jQuery實質(zhì)上是一個構(gòu)造函數(shù),接受一個參數(shù),這個參數(shù)可能是節(jié)點,然后返回一個方法對象去操作節(jié)點~~~~~這就是本質(zhì)~~~~~!!!!! 一百分
閉包不是JavaScript可以造出來的,是因為函數(shù)的作用域的特性衍生出來的一種情況.
也就是一個函數(shù),調(diào)用了外部環(huán)境變量的一個變量// 也就是說穿越時空了~~~;這個變量,和這個函數(shù)統(tǒng)稱為閉包
閉包的作用就是隱藏變量,避免被錯誤調(diào)用