本節書摘來華章計算機出版社《javascript應用程式設計》一書中的第1章,第1.15 節,作者:eric elliott 更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
在javascript中有兩類十分常見卻可以輕易規避的錯誤。第一類是文法錯誤,第二類是無意識的隐式副作用。
隐式副作用是代碼複用的大敵,因為它導緻函數被其作用域外的狀态所劫持。隐式副作用的産生是由于多個函數間共享變量或屬性所緻,舉例來說,應用中有一個購物車功能,使用者在會話期間可以對購物車的内容進行儲存。
使用者想要更改目前會話中購物車的内容順序,隻需:
很不幸,當使用者在目前會話中添加或删除購物車内容時,之後的購物車設定資訊也被連帶删除了,導緻這個問題的代碼片段是:
請留意此處,cart.items是對原型對象上items屬性的直接引用,現在對代碼做略微修改。
cart.items = object.create(items);
新的購物車擁有自己的内容副本,不會再對storedcart對象帶來直接影響。
若想減少隐式副作用在程式中的出現機率,最好的方法就是在函數内部對它進行規避。所有外部變量傳入函數之前,最好是先經過一輪複制,不要将原始值直接傳入。
純函數沒有隐式副作用,因為它在調用時不會更改任何外部變量,決定它傳回值的因素僅有一個,即它的入參。
盡可能地確定你的函數在執行過程中不會影響外界的狀态,在執行結尾處傳回修改後的變量副本而不是原始引用,請注意,在整個執行過程中你仍然有更改外部變量的機會。就像rest架構下用戶端與伺服器的資料傳輸一樣:用戶端首先從伺服器擷取一份資料資源的副本,修改其内容,再将處理過的副本發送回至伺服器。建議歸建議,大部分情況下開發者為了兼顧到應用的性能不會這麼去做,不過使用純函數或許可以起到一定效果。
在每個函數内部對隐式副作用做規避,一來可以減少代碼備援,二來可以幫助你提升程式分層設計的意識。舉例來說,你有一個開工已達數月之久的項目,現在你需要對其新增資料校驗功能,當項目中僅有一個函數能夠對資料進行送出操作時,你隻需把校驗功能安插在此函數調用之前即可。但如果這樣的函數在項目中有百來個,勢必會影響校驗功能的加入。
将不同的功能邏輯互相隔離,可以讓你更好地管理應用狀态。如果函數在執行過程中不會被外界的狀态變更所幹擾,它隻需少量代碼就可以完成手頭的工作,因為眼前的任務隻有一個。
同理,操作dom的函數一定隻專注于dom樹操作,比如視圖的render()方法,又如一些dom樹插件。