少俠們好~
又是一段時間沒見了洞翩,新的一年了稽犁,希望各位少俠最近過得都還好。
上次和大家說到了對象組合中的 mixin 和 forward骚亿,
本來按道理這次應(yīng)該繼續(xù)對象組合的話題聊下去缭付,
但是!
由于接下來的內(nèi)容會稍微更復(fù)雜一些循未,
同時我想著有些少俠出于某些奇怪的原因,根基可能不太穩(wěn)秫舌。
再加上上次結(jié)尾說了讓你們別猜的妖,猜不到的,有些人應(yīng)該不信足陨!
所以嫂粟,這次的內(nèi)容中的 JS 知識可能是次要的,更重要的是和大家分享一些小思想和經(jīng)驗墨缘,
畢竟某個具體的 JS 知識點(diǎn)可能只能幫助少俠你解決某個 JS 問題星虹,而一些通用的小套路可能會在多個領(lǐng)域?qū)δ阌袔椭?/p>
從標(biāo)題少俠你應(yīng)該也知道了,這次我們的內(nèi)容會和一些基礎(chǔ)知識有關(guān)镊讼,一些你可能都不會怎么放在心上的內(nèi)容宽涌,但是,如果你輕易的忽視它們蝶棋,在關(guān)鍵時刻卸亮,它們卻會對你產(chǎn)生蝴蝶效應(yīng)般的作用,而你甚至都意識不到這一點(diǎn)玩裙。
所以兼贸,這次的內(nèi)容可以算是一半技術(shù)文章段直,更重要的是思想~
tip:這篇文章是接著上一篇文章寫的,最好是按順序看過來的比較好溶诞。
上一篇鏈接:
回到起點(diǎn)喧务,深入理解簡單事物
一般來說,不管做什么甩苛,深入理解簡單基礎(chǔ)的事物都是很重要的蹂楣。
只有深入理解了基礎(chǔ)事物,才能更好的應(yīng)對在此這上更復(fù)雜的情況讯蒲。
所以這里我們就聊一點(diǎn)容易被忽視的基礎(chǔ)知識痊土,
在 JS 中也一樣,總有一些最基礎(chǔ)必不可少的東西墨林。
這里我們要聊到的是值赁酝。
什么是值呢?
值可以看做是 JS 中的最基礎(chǔ)的元素旭等,就像我們世界中的基礎(chǔ)元素酌呆,氫元素,氧元素等等搔耕,
而在 JS 世界中隙袁,這些元素就是字符串,數(shù)字弃榨,布爾值等等菩收。
除此之外,還有一些稍微復(fù)雜一些的元素鲸睛,
比如對象娜饵,數(shù)組,以及函數(shù)等等官辈。
知道了值之后箱舞,另外一個和它息息相關(guān)的內(nèi)容是表達(dá)式。
什么是表達(dá)式呢拳亿? 簡單來說晴股,能夠直接轉(zhuǎn)化成值的東西,就叫做表達(dá)式肺魁。
記住了队魏,少俠,表達(dá)式可以直接轉(zhuǎn)化變成一個值,但是它并不是一個值胡桨。
這次的內(nèi)容很簡單吧官帘?
沒錯,都是基礎(chǔ)知識昧谊,我們接著來看另外一個內(nèi)容刽虹,賦值。
這個時候可能會稍微有趣一些了呢诬,因為賦值雖然比較簡單涌哲,但是正因為它比較簡單,反而會讓少俠你很容易就忽略掉一些重要的東西尚镰。
你可以給一個變量賦值:
給一個對象屬性賦值:
還可以給一個數(shù)組賦值:
那么問題來了阀圾,
少俠你有沒有想過,當(dāng)你給一個變量狗唉,或者對象屬性賦值時初烘, 你到底是在往里面放什么東西,
或者說分俯,你應(yīng)該在右邊放什么東西肾筐?
當(dāng)然是一個值了對吧? 你不可以說缸剪,我在變量里面放一個運(yùn)算符吗铐,比如 + 號。
你也不能直接放各種語句杏节,至少在 JS 里面不能:
你可以放的只有值:
But! 生活總會有意外情況~
有時候唬渗,右邊會是一個表達(dá)式。
奋渔?镊逝?? 右邊變成了一個表達(dá)式卒稳,是不是意味著我們剛才說的右邊只能是一個值的規(guī)則不適用了呢?
不是他巨! 記住了充坑,少俠,賦值賦值染突,所以右邊必須得是一個值捻爷。
之所以表達(dá)式也可以放在右邊,是因為表達(dá)式可以變成一個值份企,所以我們可以先解析它也榄,獲取到一個值,然后放進(jìn)去:
“為什么可以在右邊放一個表達(dá)式呢?”
“因為表達(dá)式可以變成一個值甜紫!”
“為什么表達(dá)式可以變成一個值呢降宅?”
“因為可以變成值的東西就是表達(dá)式!”
“為什么囚霸。腰根。⊥匦停”
“哪有那么多為什么额嘿!”
所以,少俠你可以在右邊放置任何表達(dá)式劣挫,但是册养,最終,它們都會轉(zhuǎn)成一個值压固。
不管這個值是數(shù)字球拦,字符串,還是函數(shù)邓夕,只要轉(zhuǎn)換出一個可用的值刘莹,就可以了。
Ok~ 再重復(fù)一遍焚刚,如果右邊是一個表達(dá)式点弯,它會先轉(zhuǎn)換成一個值,而且矿咕,重點(diǎn)是它會到此為止抢肛!
“真啰嗦,這么基礎(chǔ)的東西碳柱,還說這么大一堆捡絮!”
“是啊是啊,還重復(fù)說莲镣!”
沒錯福稳! 為什么要重復(fù)說這個基礎(chǔ)的東西呢?
因為它會產(chǎn)生蝴蝶效應(yīng)瑞侮,
還記得上節(jié)最后提到的問題嗎的圆?
為什么 obj1.fn = () => { obj2.fn(); } 會在箭頭函數(shù)調(diào)用時再去查找 obj2.fn,而直接賦值 obj1.fn = obj2.fn 卻不在調(diào)用 obj1.fn 時再去查找 obj2 中的 fn 呢
也就是下面這樣的情況:
從上一節(jié)的內(nèi)容中半火,少俠你應(yīng)該知道越妈,第一種方式的話,屬于 early-bound钮糖,而第二種方式梅掠,屬于late-bound。
一個大的區(qū)別就是我們在過后改變了 obj2.fn 的函數(shù)后,一個會更新阎抒,另一個不會酪我。
第一種方式:
第二種方式:
造成這種差異的原因就是賦值規(guī)則導(dǎo)致的:
第一種賦值情況:
這里右邊是什么呢? 右邊是 obj2.fn
第二種賦值情況:
這里右邊是什么呢挠蛉? 右邊是 () => obj2.fn();
重點(diǎn)來了祭示! obj2.fn 是一個表達(dá)式! 而 () => obj2.fn() 是一個函數(shù)谴古!
我們已經(jīng)提到過质涛,賦值的右邊必須是值,而 obj2.fn 是表達(dá)式掰担,所以我們必須解析它汇陆,直到獲得一個值。
而另外一種情況呢带饱?
() => obj2.fn() 是一個函數(shù)毡代,而函數(shù)本身就是一個值,所以我們不需要做任何操作勺疼!
我們這里并不會再去關(guān)心函數(shù)內(nèi)部 obj2.fn 是什么情況教寂,因為函數(shù)還沒有觸發(fā),而賦值的話由于外部箭頭函數(shù)已經(jīng)是一個值了执庐,所以到這也就結(jié)束了酪耕。
所以,第一種情況下,賦值結(jié)束后,obj1.fn 和 obj2.fn 沒有任何關(guān)聯(lián)了勋功,
每次調(diào)用 obj1.fn,會直接調(diào)用這個函數(shù)盟步。
而第二種情況則會和 obj2.fn 有關(guān)聯(lián):
每次調(diào)用 obj1.fn 時,進(jìn)入到箭頭函數(shù)內(nèi)部躏结,都會重新查找一遍 obj2.fn却盘,并調(diào)用它。
很神奇吧媳拴?
現(xiàn)在少俠你知道為什么obj1.fn = obj2.fn 會立刻查找 obj2.fn 的值了吧黄橘,因為 賦值操作右邊必須是值,而 obj2.fn 不是禀挫,所以會先解析它旬陡,直到獲取到一個可用的值拓颓。
而 obj1.fn = () => obj2.fn(); 由于右邊就是一個函數(shù)语婴,函數(shù)本身就是一個值了,所以會到此為止,并不會再去關(guān)心函數(shù)內(nèi)部什么情況砰左。
造成這樣差距的匿醒,就是和一個小小的賦值運(yùn)算有關(guān)。
“有時候缠导,讓你陷入麻煩的并不是你不知道的事廉羔,而是那些你自以為了解,但實(shí)際上卻是錯誤的事僻造”锼————馬克吐溫”
直覺與規(guī)則,應(yīng)該相信哪一個髓削?
這里另外一個有趣的地方就是函數(shù)必須是惰性的竹挡,這樣我們才可以利用一個中間的箭頭函數(shù)實(shí)現(xiàn) late-bound obj2.fn。
惰性的意思也就是說立膛,函數(shù)內(nèi)部的事情揪罕,必須要在它被調(diào)用時候,才產(chǎn)生效果宝泵。
你不調(diào)用它的時候好啰,就什么也不會發(fā)生。
即使它內(nèi)部可能很危險:
這個其實(shí)挺合理的儿奶,盡量只加載必要的內(nèi)容框往,在需要時候再去查找相關(guān)的內(nèi)容,肯定比每次一開始就將所有內(nèi)容全部加載要好很多廓握。
所以搅窿,就算你在函數(shù)內(nèi)部引用了一大堆變量,也只會在調(diào)用它時才開始查找:
甚至你函數(shù)內(nèi)部引用了未定義的變量隙券,只要你不觸發(fā)它男应,也不會報錯:
理所當(dāng)然的,既然是在函數(shù)調(diào)用時才開始查找對應(yīng)的元素娱仔,那么如果元素中途發(fā)生了改變沐飘,也應(yīng)該以最后一次為準(zhǔn),對吧牲迫?
舉個更貼近現(xiàn)實(shí)的例子耐朴,
如果一個妹子和你只是普通朋友關(guān)系,直接親可能臉都要被打腫盹憎,但是如果先想辦法追到手筛峭,變成女朋友了,情況可能就不一樣了陪每。
當(dāng)然影晓,這里還是順便說一下如果有普通朋友關(guān)系也可以親的妹子請聯(lián)系我镰吵!
“。挂签。疤祭。?饵婆?勺馆?”
“一天都弄些什么亂七八糟的例子!G群恕草穆!”
好了,現(xiàn)在我們回頭看的話搓译,下面這樣的情況少俠你應(yīng)該就很好理解了:
OK续挟,現(xiàn)在,少俠你知道了賦值的規(guī)則侥衬,知道了函數(shù)是惰性的诗祸,知道了如果函數(shù)中引用了一個變量,在函數(shù)調(diào)用時才會去查找轴总,也知道了應(yīng)該以這個變量最后調(diào)用時的值為準(zhǔn)直颅,balabala。怀樟。功偿。
按照道理來說,少俠你應(yīng)該已經(jīng)能夠處理相關(guān)的問題了往堡,
但是~
少俠你的直覺有時候會欺騙你
這里調(diào)用兩次函數(shù)的結(jié)果是什么呢械荷?
如果少俠你認(rèn)為是 0 和 1 的話,就說明在 JS 規(guī)則和你的直覺之間虑灰,你相信了后者吨瞎。
正確答案是 2 2。
如果少俠你真的按照我們所說的JS規(guī)則穆咐,一步一步分析的話颤诀,結(jié)果應(yīng)該是下面這樣:
而認(rèn)為結(jié)果是0 和 1 的原因是少俠你的大腦忽略了 JS 世界中的規(guī)則,轉(zhuǎn)而采用了更快更輕松的直覺感受对湃,你的直覺會發(fā)現(xiàn)每次遍歷時 i 是 0 和 1崖叫,它會自然的認(rèn)為函數(shù)里的 i 每次也是 0 和 1。
這是你大腦第一反應(yīng)的規(guī)則:
但事實(shí)上拍柒,是函數(shù)里面的 i 和遍歷時的 i 沒有關(guān)系心傀,因為函數(shù)是惰性的,它里面的 i 要等到調(diào)用時才開始查找拆讯。
跟隨大腦的想法
好了脂男,經(jīng)過上面的內(nèi)容恐锦,少俠你應(yīng)該知道了規(guī)則和直覺有時候會產(chǎn)生沖突,
大腦的第一直覺不一定總是可靠疆液。
不過,
大腦雖然會犯錯陕贮,但是它也有很多好處堕油,
比如如果不是它知道如何控制你用嘴巴吃飯,你可能會餓死肮之!
另外一個好處就是它也喜歡觀察并總結(jié)發(fā)現(xiàn)的事物規(guī)律掉缺,
大腦經(jīng)常也會很好奇,可能會產(chǎn)生一些奇怪的腦洞戈擒,有時候眶明,跟隨大腦的想法,也能夠幫助你發(fā)現(xiàn)新大陸筐高。
比如搜囱,我們上面的函數(shù)都沒有使用到 this,
如果你碰巧又才學(xué)習(xí)了 this柑土,
你的大腦可能會想蜀肘,如果將 this 考慮進(jìn)來,會發(fā)生什么事呢稽屏?
這里我們結(jié)合上一節(jié)的內(nèi)容看看扮宠,
第一種情況:
第二種情況:
很熟悉的內(nèi)容,因為這就是我們上一次提到的 mixin 和 forward 的情況狐榔。
由于上一節(jié)已經(jīng)詳細(xì)說過這些內(nèi)容了坛增,所以這里就簡單說下結(jié)果,
第一種情況調(diào)用 obj1.fn 會打印出 obj1 中的 name薄腻,'天辰dreamer'收捣。
而第二種情況調(diào)用 obj1.fn 會打印 obj2 中的 name,也就是 '烏云dreamer'庵楷,
而且由于我們的箭頭函數(shù)是惰性的原因坏晦,第二種情況可以在中途改變 obj2.fn 的內(nèi)容,obj1.fn 會自動更新嫁乘。
還記得我們上一次的表格嗎昆婿?
組合方式 | bound 類型 | 方法中的作用對象 | 數(shù)據(jù)是否獨(dú)立 |
---|---|---|---|
mixin | early-bound | 對象本身 | 是,每個對象的操作不會影響其他 mixin 對象 |
forward | late-bound | 用于組合的對象 | 否蜓斧,用于所有對象會共享 forward 進(jìn)來的對象數(shù)據(jù)仓蛆,所以會互相影響 |
如果少俠你仔細(xì)觀察的話,你可能會想挎春,
obj1.fn = obj2.fn 中看疙,它是 early-bound豆拨,同時方法中的 this 作用于 obj1。
而 obj1.fn = () => { obj2.fn() } 中能庆,它是 late-bound, 同時方法中的 this 會指向 obj2施禾。
是不是好像缺了兩種情況?
比如能不能實(shí)現(xiàn) early-bound搁胆,而 this 作用于 obj2弥搞,
或者實(shí)現(xiàn) late-bound, this 卻作用于 obj1 上呢?
哈哈哈哈哈哈~
沒想到吧渠旁!又繞回來了攀例!
劇情居然突然變得陡峭了起來,基礎(chǔ)不穩(wěn)的少俠有沒有躲在一旁瑟瑟發(fā)抖顾腊?是不是有點(diǎn)措手不及粤铭?
“。杂靶。梆惯。。吗垮。加袋。。抱既。职烧。》辣茫”
好了蚀之,嚴(yán)肅臉!
不是故意花里胡哨捷泞,這些內(nèi)容是我認(rèn)為少俠你應(yīng)該理解的足删,理解它們對你熟練掌握J(rèn)S很有幫助,同時能避免很多日乘遥坑失受,也對我們接下來要遇見的 prototype 有很大幫助。
如果你覺得沒用的話咏瑟,我不要你覺得拂到,我要我覺得!
那么码泞,最后兩種情況到底能不能實(shí)現(xiàn)呢兄旬?
“當(dāng)然可以了,不可以的話余寥,天辰你提它們干嘛领铐?”
“我隨便說一說不行嘛悯森?”
“騙誰呢,肯定可以绪撵∑耙觯”
“那我這里說它不可以∫粽”
“不可以算了幻碱,反正我們也沒興趣「耐В”
“少俠你怎么能說放棄就放棄呢? 再試一試坟岔≮诵郑”
“不試!”
“我糾正一下剛說過的話社付,是可以實(shí)現(xiàn)的承疲。”
“沒興趣了鸥咖⊙喔耄”
“不會很難的√淅保”
“就不試啊研!”
“。鸥拧。党远。。富弦。沟娱。”
天辰突然和自己內(nèi)心幻想出來的角色吵了起來腕柜,一時生氣直接跑走了济似,臨走前扔下了一張皺巴巴的小紙條。盏缤。砰蠢。
1、函數(shù)是惰性的唉铜,所有放在函數(shù)內(nèi)部的變量娩脾,都會在該函數(shù)調(diào)用時才開始查找,所以 early-bound 和 late-bound 的關(guān)鍵區(qū)別可能是元素放置在函數(shù)內(nèi)外的不同打毛。
2柿赊、你可以通過將普通函數(shù)放置在不同對象上調(diào)用來改變其中的 this 指向俩功,你需要 this 指向 a, 你就放在 a 上調(diào)用,你需要 this 指向 b, 你就放在 b 上調(diào)用碰声。
3诡蜓、重新回顧一下我們最開始提到的很基礎(chǔ)的規(guī)則可能會有幫助。
4胰挑、少俠蔓罚,江湖路遠(yuǎn),有緣再見~
一些你可能關(guān)心的問題
1瞻颂、感覺更新有點(diǎn)慢豺谈,天辰你能不能更新快一點(diǎn)?
不好弄贡这,要有靈感了才能寫茬末,而且如果我自己讀著都比較尷尬的話就不好意思發(fā)出來,得反復(fù)改很多次才行盖矫。丽惭。。
2辈双、說好的藍(lán)胖dreamer圖片呢责掏?
好了,這就是可愛又聽話的藍(lán)胖dreamer了~
你可能會以為藍(lán)胖會是只英短貓湃望,但是我叫它藍(lán)胖的原因只是因為它眼睛是藍(lán)色的很好看换衬,然后它長得又比較胖。证芭。冗疮。
3、這次的文章有點(diǎn)奇怪檩帐,感覺好像你說了一大堆术幔,又感覺好像什么都沒說。
很好湃密,說明我的文章已經(jīng)超出了單純的文章本身诅挑!已經(jīng)有點(diǎn)道的感覺了,只可意會不可言傳~
3泛源、好吧好吧拔妥,那么下一次會有 prototype 嗎?达箍!
為什么要急著遇見什么呢没龙?少俠。
說不定當(dāng)我們真正遇見了 prototype 之后,你反而會開始懷念起現(xiàn)在的時刻呢~
4硬纤、文章結(jié)尾是不是太倉促隨意了解滓?
這還叫倉促隨意?少俠你應(yīng)該是沒有看過更倉促的結(jié)尾方式筝家,比如:
聲明:本文僅限于瀟灑有趣又很酷的天辰dreamer裝逼使用洼裤,轉(zhuǎn)載請注明原作者和出處,商業(yè)轉(zhuǎn)載請聯(lián)系我(如果真有的話)溪王。腮鞍。。