करींग, फ़ंक्शन कंपोज़िशन और इम्यूटेबल डेटा के साथ अपने कोड को संरचित करें ताकि पूर्वानुमेयता और परीक्षण-योग्यता प्राप्त हो।
इस पाठ को Kodokon में खोलेंJavaScript फ़ंक्शनों को प्रथम-श्रेणी मान के रूप में मानता है, जो फ़ंक्शनल पैटर्न के लिए द्वार खोलता है। करींग n तर्कों वाले किसी फ़ंक्शन को एकल-तर्क फ़ंक्शनों की एक श्रृंखला में बदल देता है: f(a, b, c) f(a)(b)(c) बन जाता है। इसे आंशिक अनुप्रयोग (partial application) के साथ भ्रमित न करें, जो एक ही चरण में कुछ तर्कों को स्थिर कर देता है (fn.bind(null, a))। करींग सामान्य फ़ंक्शनों से विशेषीकृत फ़ंक्शन बनाने में चमकता है।
const curry = (fn) => {
const arity = fn.length;
return function curried(...args) {
if (args.length >= arity) return fn(...args);
return (...rest) => curried(...args, ...rest);
};
};
const add3 = (a, b, c) => a + b + c;
const addCurried = curry(add3);
console.log(addCurried(1)(2)(3)); // 6
console.log(addCurried(1, 2)(3)); // 6एक स्पेक सूक्ष्मता: fn.length केवल उन पैरामीटरों को गिनता है जो पहले डिफ़ॉल्ट या rest पैरामीटर से पहले स्थित हैं। (a, b = 1) => {} की length 1 है, (...args) => {} की 0। इसलिए arity-आधारित curry को सरल पैरामीटरों वाले फ़ंक्शन दिए जाने चाहिए। कंपोज़िशन अगला कदम है: छोटे शुद्ध फ़ंक्शनों को पठनीय पाइपलाइनों में जोड़ना।
const pipe = (...fns) => (input) =>
fns.reduce((acc, fn) => fn(acc), input);
const trim = (s) => s.trim();
const lower = (s) => s.toLowerCase();
const dashes = (s) => s.replace(/\s+/g, "-");
const toSlug = pipe(trim, lower, dashes);
console.log(toSlug(" Hello World "));
// "hello-world"pipe(f, g, h)(x) h(g(f(x))) की गणना करता है: आप इसे निष्पादन क्रम में पढ़ते हैं। compose संस्करण गणितीय संकेतन की तरह दाएँ से बाएँ लागू होता है। ये पाइपलाइनें केवल तभी मूल्यवान हैं जब फ़ंक्शन शुद्ध हों - कोई साइड इफ़ेक्ट नहीं, कोई छिपी हुई निर्भरता नहीं - जो इम्यूटेबल डेटा की माँग करता है: किसी वस्तु को म्यूटेट करने के बजाय, आप उसका एक नया संस्करण बनाते हैं, और तब किसी परिवर्तन का पता लगाने के लिए संदर्भ समानता ही पर्याप्त होती है (React के reconciliation का हृदय)।
const state = Object.freeze({
user: { name: "Ada" },
tags: ["js"]
});
const next = {
...state,
tags: [...state.tags, "fp"]
};
const deepCopy = structuredClone(state);
deepCopy.user.name = "Grace"; // independent copybind के साथ काम करता है, करींग केवल ऐरो फ़ंक्शन के साथpipe(f, g, h)(x) किसके समकक्ष है?const s = Object.freeze({ a: { b: 1 } }) के बाद, क्या असाइनमेंट s.a.b = 2 काम करता है?s.a फ़्रीज़ नहीं है