更多相關内容見部落格 github.com/zhuanyongxi… 概念:
副作用是在計算結果的過程中,系統狀态的一種變化,或者與外部世界進行的可觀察的互動。上文中
的純函數的概念很嚴格,這個副作用的概念也是。它的要求很高,概括的講,隻要是跟函數外部環境發生的互動就都是副作用。從“副作用”這個詞語來看,它更多的情況在于“改變系統狀态”。
在
教程中列舉的一些副作用:
- 更改檔案系統
- 往資料庫插入記錄
- 發送一個http請求
- 可變資料
- 列印/log
- 擷取使用者輸入
- DOM查詢
- 通路系統狀态
如果完全沒有副作用,那我們的代碼就是單純的跑一遍浪費了一點電而已,除此之外什麼都沒有發生,這樣的話我們寫代碼就沒有意義了。是以,在JS中,我們的目的不是完全消除副作用注1,而是避免那些不應該出現的副作用。
JS原生的方法中,
map
就很函數式,他會傳回一個新的數組,不會改變原數組。而
pop
這種方法就很不好,它在操作了數組之後,也改變數組本身。
是以當我們要使用那些有副作用的方法寫純函數的時候,記得做一次深拷貝:
例1
const myPop = x => {
let [...y] = x;
return y.pop();
}
使用一個固定的共享狀态或者調用一個純函數不算是副作用,例子如下:
例2
const a = 5;
function A(b) {
return a + b;
}
A(5);
調用純函數的例子:
例3
function foo(x) {
return bar(x);
}
function bar(y) {
return y + 1;
}
foo(1);
雖然不算是副作用,可更加推薦的方式是把函數bar用參數的方式傳進來,這樣就做到了解耦,用起來更加的友善:
例4
function foo(fn, x) {
return fn(x);
}
function bar(y) {
return y + 1;
}
foo(bar, 1);
如果使用柯裡化的方式,會更加的清爽和友善:
例5
function foo(fn) {
return function(x) {
return fn(x);
}
}
function bar(y) {
return y + 1;
}
foo(bar)(1);
這個例子依然存在一個會令我們感到不安的地方,那就是bar可能會被修改。例如:
例6
function foo(fn, x) {
return fn(x);
}
function bar(y) {
return y + 1;
}
bar = undefined;
foo(bar, 1);
當然我們平時很少會大腦抽筋在全局作用域下寫出一個
bar = undefined
來讓我們的系統出錯,這更可能在某個有副作用的函數内出現這種情況。這就是為什麼我們要避免副作用。這個情況在ES6中會得到改善,例如:
例7
const foo = function(fn, x) {
return fn(x);
}
const bar = function(y) {
return y + 1;
}
bar = undefined; // error
foo(bar, 1);
個人建議用
const
的方式,這樣更加的安全,即便出錯也可以快速定位。
注釋:
- 注1: 如果繼續深入學習,對與上面列出的一些副作用,函數式還有一種延遲執行的方式(IO容器)來使這些操作變純。
參考資料:
原文釋出時間為:2018年06月14日
原文作者:磚用冰西瓜
本文來源:
掘金 https://juejin.im/entry/5b3a29f95188256228041f46如需轉載請聯系原作者