Javascript设计模式与开发实践读书笔记(1-3章)
第一章 面向?qū)ο蟮腏avascript
1.1 多態(tài)在面向?qū)ο笤O(shè)計中的應(yīng)用??
多態(tài)最根本好處在于,你不必詢問對象“你是什么類型”而后根據(jù)得到的答案調(diào)用對象的某個行為--你只管調(diào)用行為就好,剩下的一切多態(tài)會搞定
換句話說就是:多態(tài)的最根本作用就是把過程化的條件分支語句轉(zhuǎn)化為對象的多態(tài)性,從而消除這些條件分支語句
?例子:假設(shè)有一個地圖應(yīng)用,每個地圖API提供商都提供了show方法,負責(zé)在頁面上顯示地圖,首先我們用一些分支條件語句來實現(xiàn)一個調(diào)用方法renderMap
此時一旦需要增加搜搜地圖的應(yīng)用,就必須改動renderMap函數(shù),繼續(xù)在里面堆砌分支條件語句
我們必須將程序中相同的部分抽象出來,那就是顯示整個地圖
?
那么此時,即使以后增加了搜搜地圖,renderMap也不需要做什么改變
?
1.2 對象會記住它的原型
就Javascript的真正實現(xiàn)來說,不能說對象有原型,而只能說對象的構(gòu)造器有原型,對“對象把請求委托給它自己的原型”這句話, 更好的說法是對象把請求委托給它的構(gòu)造器原型,
javascript對象通過一個名為_proto_的隱藏屬性,來將請求轉(zhuǎn)交給它的構(gòu)造器,對象的_proto_會指向的它的構(gòu)造器對象,實際上,_proto_就是對象跟“對象構(gòu)造器原型”聯(lián)系起來的紐帶
?
1.3 如果對象無法響應(yīng)請求,會把請求委托給它的構(gòu)造器原型
當對象需要a需要借用對象b的能力時,可以選擇性的把對象a的構(gòu)造器的原型指向?qū)ο骲,從而達到繼承的目的
- 首先,嘗試遍歷對象a的所有屬性,沒有找到name這個屬性
- 查找name屬性的這個請求被委托給對象a的構(gòu)造器原型,它被a._proto_記錄著并且指向A.prototype,而A.prototype指向obj.
- 在對象obj中找到了name屬性,并返回了它的值
當我們期望得到一個“類”繼承自另外一個“類"的效果時,往往會使用下面的方式
?
第二章 this、call和apply
2.1 this的指向?
this的指向大致可以分為以下4種:
- 作為對象的方法調(diào)用
- 作為普通函數(shù)調(diào)用
- 構(gòu)造器調(diào)用
- Function.prototype.call或Function.prototype.apply調(diào)用(動態(tài)的改編傳入函數(shù)的this)
例子:在div節(jié)點事件函數(shù)內(nèi)部,有一個局部的callback方法,callback在調(diào)用時,內(nèi)部的this會指向window
而我們想讓它指向div節(jié)點,可以用一個變量保存div節(jié)點的引用
?
2.2 call和apply的區(qū)別
apply接受兩個參數(shù),第一個參數(shù)指定了函數(shù)體內(nèi)的this對象的指向,第二個參數(shù)為一個帶下標的集合,可以為數(shù)組,也可以是類數(shù)組,apply方法將這個集合中的元素作為參數(shù)傳遞給被調(diào)用的函數(shù)
call傳入的參數(shù)不固定,第一個也是代表函數(shù)體內(nèi)this的指向,第二個參數(shù)開始,每個參數(shù)依次被傳入函數(shù)
javascript不計較形參實參和順序上的區(qū)別,javascript內(nèi)部的參數(shù)就是用一個數(shù)組來表示的,所以apply使用的更頻繁一點,我們不必關(guān)心具體有多少個參數(shù)要傳入給函數(shù),只需要一股腦的推過去就好了
如果我們明確知道函數(shù)接受多少個參數(shù),而且想一目了然的表達形參和實參的關(guān)系,那么也可以用call來傳送參數(shù)
?
第三章 閉包和高階函數(shù)
3.1 變量的生命周期
假設(shè)頁面上有5個div節(jié)點,我們通過循環(huán)來給每個div綁定onclick事件,按照索引順序,點擊第一個div時彈出0,點擊第二個div時彈出1,依次類推,代碼如下:
但由于onclick是異步出發(fā),當事件觸發(fā)時,for循環(huán)早已結(jié)束,此時i已經(jīng)是5,所以輸出一直是5,解決方法是把每次循環(huán)的i封閉起來,當在事件函數(shù)中順著作用于鏈從內(nèi)到外查找i時,會先找到被封閉在閉包環(huán)境中的i
?
3.2 封裝變量
把一些不需要暴露在全局的變量封裝成私有變量,即封閉在函數(shù)內(nèi)部, 減少頁面中的全局變量
封閉在函數(shù)內(nèi)部的變量或函數(shù),只會在初始化閉包函數(shù)的時候執(zhí)行一次,以后每一次調(diào)用函數(shù),將不再執(zhí)行封閉在函數(shù)內(nèi)部的代碼,這也是閉包的一大好處
?
3.3 閉包和面向?qū)ο笤O(shè)計
通常面向?qū)ο竽軐崿F(xiàn)的思想,用閉包也能實現(xiàn),先來看看跟閉包相關(guān)的代碼:
如果換成面向?qū)ο蟮膶懛?#xff0c;就是:
?
3.4?高階函數(shù)
?高階函數(shù)是指至少滿足下列條件之一的函數(shù):
- 函數(shù)作為參數(shù)被傳遞
- 函數(shù)作為返回值輸出
?1?函數(shù)作為參數(shù)被傳遞
將一些難以復(fù)用的代碼提取出來,用回調(diào)函數(shù)的形式傳入處理函數(shù),如
?
Array.prototype.sort的使用可以看到,我們的目的是對數(shù)組進行排序,這是不變的部分,而使用什么規(guī)則去排序,這是可變的部分,把可變的部分封裝在函數(shù)參數(shù)里,動態(tài)傳入
?
3.5 函數(shù)柯里化(function currying)
currying 又稱部分求值,一個currying首先會接受一個參數(shù),接受這個參數(shù)之后,并不會馬上求值,而是繼續(xù)返回另外一個函數(shù),剛才傳入的參數(shù)在函數(shù)形成的閉包中被保存起來,待到函數(shù)被真正需要求值的時候,之前傳入的所有參數(shù)都會一次性求值
首先來看下一種currying函數(shù)的實現(xiàn),方便了解其思想
再來看一個通用的function currying() {} ,function currying() {}接受一個參數(shù),即將要被currying的函數(shù)
?
3.6 函數(shù)節(jié)流
假設(shè)一個函數(shù)被觸發(fā)的概率非常高,就需要采取一些函數(shù)節(jié)流的方式實現(xiàn)
?
3.7 分時函數(shù)
有些函數(shù)需要用戶主動調(diào)用,但因為一些客觀原因,這些函數(shù)會嚴重影響頁面性能,比如說我們要在短時間內(nèi)要往頁面中大量加載DOM節(jié)點,處理這一類問題的解決方案就是使用timeChunk函數(shù)讓創(chuàng)建節(jié)點的工作分批進行,比如1秒創(chuàng)建1000個節(jié)點,改為每200毫秒創(chuàng)建8個節(jié)點
timeChunk函數(shù)接受3個參數(shù),第一個參數(shù)是創(chuàng)建節(jié)點所用到的數(shù)據(jù),第二個參數(shù)是創(chuàng)建節(jié)點邏輯的函數(shù),第三個參數(shù)表示每一批創(chuàng)建的節(jié)點數(shù)量
?
3.8 惰性加載函數(shù)?
比如我們需要一個要在瀏覽器中綁定時間的addEvent函數(shù)
這個函數(shù)的缺點就是,當它每次被調(diào)用的時候都會執(zhí)行里面的if條件分支語句
第二種方案就是,在代碼加載的時候執(zhí)行一次判斷,以便讓addEvent包裹正確邏輯的函數(shù),代碼如下
但目前這個函數(shù)還是有一個缺點,假設(shè)我們從頭到尾都沒有使用過addEvent函數(shù)呢?
第三種方案就是所使用的惰性加載方案,在第一次進入條件分支的時候,在函數(shù)內(nèi)部會重寫這個函數(shù),重寫之后的函數(shù)就是我們期望的addEvent函數(shù),在下一次進入addEvent函數(shù)的時候,addEvent就不存在那些分支判斷
轉(zhuǎn)載于:https://www.cnblogs.com/elexiang/p/4803259.html
總結(jié)
以上是生活随笔為你收集整理的Javascript设计模式与开发实践读书笔记(1-3章)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《浪潮之巅》读书笔记2
- 下一篇: MapReduce实现计数