iT邦幫忙

2022 iThome 鐵人賽

DAY 12
0

當它越難拿到,你就會越想留住。

Jay Mark Mateo Balmes

本篇不是討論Partial Applications本身,而是他在控制流程中的優勢!

正如昨天說提到的,某些邏輯需要被抽離成函式時,是包含條件的,或是參數是依情況而定的,此時基於closure的partial applications就是使用的最佳時機。舉例來說,我們有個functionpower,他會取三個數字作為引數,並且由左至右做冪次。這個例子複雜之處就是,該函式也容許並非三個引數都有值。

直觀的寫法可能會長這樣:

// 未使用partial applications
// 可能會被討厭的寫法
function power(n1, n2, n3) {
    if (n1 && !n2) {
        return n1;
    }
    
    if (n1 && !n3) {
        return n1 ** n2;
    }
    
    if (n1 && n2 && n3) {
        return (n1 ** n2) ** n3;
    }
}

console.log(power(2)); //2
console.log(power(2, 3)); //8
console.log(power(2, 3, 3)); //512

在這個寫法中,當參數變多,很快就會令人困惑。因為我們需要對輸入做校驗,因此需要非常多的if陳述句。順帶一提,我們可以仔細看這些if陳述句,看看這個函式做了哪些前提假設。

建構Partial Applications

為了解決上述問題,我們可以用partial application重構power

// 使用partial applications
// 比較不會被討厭的寫法
function power(n1) { 
    return (n2) => {
        return n2 ? power(n1 ** n2) : n1;
    }
}

console.log(power(2)()); //2
console.log(power(2)(3)()); //8
console.log(power(2)(3)(3)()); //512

我們可以看到這個例子中,代碼簡潔了許多。不僅如此,我們可以做無限次的冪次。事實上,或許有人看到這個例子的代碼初期會比較困惑,因為這個例子中牽涉到遞迴的使用。接下來,我們來看一個更輕量級在React中的例子。

React中的例子

我們這邊非常的簡單地考量React中雙向綁定表單欄中的輸入值。

const App = () => {
  const [username, setUsername] = useState('');
  
  const setInput = (setter) => (event) => {
    setter(event.currentTarget.value);
  }
  
  return(
    <form>
        <input
          value={username}
          onChange={setInput(setUsername)}
        />
    </form>
  );
}

在這裡,我們不用多個function calls,我們使用partial application(這裡同時是currying)把setter function最為引數,並返回hanlder給onChange prop.


上一篇
延宕滿足:Partial Applications (1/2)
下一篇
時光隧道:Passing Arguments與Returning Data
系列文
被討厭的前端實務手冊|JS x TS x React18
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言