What is Functional Programming?
ν¨μν νλ‘κ·Έλλ° ν¨λ¬λ€μ
μλ°μ€ν¬λ¦½νΈλ ν¨μν νλ‘κ·Έλλ° ν¨λ¬λ€μμ μΆκ΅¬νλ©° μΆκ°λ‘ κ°μ²΄μ§ν₯ νλ‘κ·Έλλ° ν¨λ¬λ€μλ μ§μνλ€.
- κ°μ²΄μ§ν₯ νλ‘κ·Έλλ° ν¨λ¬λ€μμ μ¬λ¬ ν¨ν΄μ μ μ©νλ €λ©΄ ν΄λμ€(μμ)μ κ°μ²΄λ₯Ό νμ©ν μ μλ€.
- νμ μ€ν¬λ¦½νΈλ₯Ό ν΅ν΄ μΈν°νμ΄μ€(λ€νμ±)λ₯Ό λμ ν μ μλ€.
λ°λΌμ μλ° κ°λ°μκ° κ°μ²΄μ§ν₯ νλ‘κ·Έλλ°μ λͺ¨λ μ΄ν΄νλ κ²κ³Ό κ°μ΄ μλ°μ€ν¬λ¦½νΈ κ°λ°μκ° μ λλ‘ κ°λ°νκΈ° μν΄μ ν¨μν νλ‘κ·Έλλ°μ λν λͺ¨λ μ΄ν΄κ° νμνλ€.
μΌκΈν¨μ: ν¨μ λ³μ + ν¨μ νλΌλ―Έν° + ν¨μ λ°ν
μΌκΈν¨μλ, μΌκΈ κ°μ²΄λ‘ μ·¨κΈλλ κ°λ μ΄λ€. ν¨μκ° λ§μΉ μ«μλ λ¬Έμμ΄μ²λΌ μΌλ°μ μΈ κ°μΌλ‘ λ€λ£¨μ΄μ§ μ μλ€λ μλ―Έ.
μΌκΈ ν¨μλ₯Ό μ§μνλ μΈμ΄λ ν¨μλ₯Ό λ³μμ μ μ₯νκ±°λ, ν¨μμ μΈμλ‘ μ λ¬νκ±°λ, ν¨μμ λ°νκ°μΌλ‘ λ°νν μ μλ€.
λ°λΌμ μΌκΈ ν¨μλ ν¨μλ₯Ό λ³μμ²λΌ λ€λ£° μ μλ€λ μλ―Έ.
1. ν¨μ λ³μ ν λΉ: ν¨μ ννμμΌλ‘ ν λΉλ ν¨μλ₯Ό λ³μμ μ μ₯ν μ μλ€.
const assignment = function() {
return "Hello World";
};
console.log(assignment()); // "Hello World"
2. ν¨μ νλΌλ―Έν° μ λ¬: ν¨μλ₯Ό λ€λ₯Έ ν¨μμ νλΌλ―Έν°λ‘ μ λ¬ν μ μλ€.
function Callback(callback) {
console.log(callback());
}
Callback(assignment); // "Hello"
var array = [ 1, 2, 3, 4 ]
var parameter = (element) => {
return element * 10
}
var calcarray = array.map(parameter)
console.log(calcarray) // "[ 10, 20, 30, 40 ]"
3. ν¨μ λ°ν: ν¨μλ λ λ€λ₯Έ ν¨μλ₯Ό λ°νν μ μλ€.
function firstFunction(){
return function() {
return "Hello secondFunction"
};
}
const secondFunction = firstFunction();
console.log(secondFunction()); // "Hello secondFunction"
function returnvalue(unit) {
return (parameter) => {
console.log(parameter * unit)
}
}
var returned = returnvalue(10)
returned(1230) // "12300"
μμν¨μ - Thread-Safe: No Side-Effects
μμ ν¨μλ μΈλΆ μνμ μμ‘΄νμ§ μμΌλ©°(μ°Έμ‘° ν¬λͺ μ±: Referentially Transparent), κ°μ μ λ ₯μ΄ μ£Όμ΄μ§λ©΄ νμ κ°μ μΆλ ₯μ λ°ννκ³ , μΈλΆ μνλ₯Ό λ³κ²½νμ§ μλλ€(λΆμ ν¨κ³Ό μμ: No Side-Effects). λ°λΌμ μ°Έμ‘° ν¬λͺ μ±κ³Ό λΆμ ν¨κ³Ό μμ μ΄λΌλ λ κ°μ§ μ€μν νΉμ±μ κ°μ§κ³ μλ€.
μμ ν¨μλ λ©ν°μ€λ λ νκ²½μμ μμ νλ€. (Thread-Safe)
Thread-Safe(λ©ν°μ€λ λ μμ μ±)
- λ³λ ¬μ μΌλ‘ μνλλ λͺ¨λ ν¨μλ€μ μλ‘μκ² μν₯μ μ£Όμ΄μ μλκ³ , μΈλΆμ κ°μ λ³κ²½ν΄μλ μλλ€.
- νλμ μμ μ μ¬λ¬κ°λ‘ λλμ΄ μνν λ€ ν©μ³€μλ, νλμ μμ μ νλ²μ μννμλμ κ°μ κ²°κ³Όμ¬μΌ νλ€.
ν¨μν νλ‘κ·Έλλ°: ν¨μν νλ‘κ·Έλλ°μμ μ°λ¦¬κ° μ¬μ©νλ λͺ¨λ ν¨μ λ¨μλ€μ μμν¨μμ¬μΌ νλ€.
μ°Έμ‘° ν¬λͺ μ±(Referentially Transparent)
μ°Έμ‘° ν¬λͺ μ±μ κ°μ μ λ ₯ κ°μ λν΄ νμ κ°μ κ²°κ³Όλ₯Ό λ°ννλ νΉμ±μ μλ―Ένλ€.
function add(a, b) {
return a + b;
}
console.log(add(1, 2)); // 3
console.log(add(1, 2)); // 3(νμ λμΌν μΆλ ₯)
λΆμ ν¨κ³Ό μμ(No Side-Effects)
λΆμ ν¨κ³Όκ° μλ ν¨μλ ν¨μκ° μ€νλμ΄λ μΈλΆ μνλ λ³μλ₯Ό λ³κ²½νμ§ μλ ν¨μλ₯Ό μλ―Ένλ€.
let count = 0;
function pureAdd(x, y) {
return x + y; // μΈλΆ μνμ μν₯μ μ£Όμ§ μμ
}
function impureAdd(x) {
count += x; // μΈλΆ μν(count)λ₯Ό λ³κ²½νλ λΆμ ν¨κ³Ό
}
μμ ν¨μμ μ₯μ
- Testability(ν μ€νΈ μ©μ΄μ±): μΌμ ν μ λ ₯ κ°μ λν΄ λμΌν κ²°κ³Όλ₯Ό λ°ννκΈ° λλ¬Έμ ν μ€νΈκ° μ©μ΄νλ€.
- Debugging(λλ²κΉ μ©μ΄μ±): μΈλΆ μνμ μμ‘΄νμ§ μμΌλ―λ‘ ν¨μμ λ²κ·Έλ₯Ό μ½κ² μΆμ ν μ μλ€.
- Memoization(λ©λͺ¨μ΄μ μ΄μ κ°λ₯μ±): κ°μ μ λ ₯μ λν΄ μΊμ±λ κ²°κ³Όλ₯Ό μ¬μ©ν μ μμ΄ μ±λ₯μ΄ ν₯μλλ€.
λΉμμ ν¨μμ λ¨μ
- Side-Effect λΆμν¨κ³Ό λ°μ: λΉμμ ν¨μλ μΈλΆ μνλ₯Ό λ³κ²½νμ¬, κ·Έ κ²°κ³Όλ‘ μ½λμ λ€λ₯Έ λΆλΆμμ λ¬Έμ κ° λ°μν μ μλ€.
- Unpredictable Output μμμΉλͺ»ν κ²°κ³Ό: λΉμμ ν¨μλ μΈλΆ μνμ μμ‘΄νλ―λ‘, λμΌν μ λ ₯κ°μ λ£μμ λ μν©μ λ°λΌ λ€λ₯Έ κ²°κ³Όκ° λμ¬ μ μλ€.
- Difficult to Reason λλ²κΉ λ° νλ‘κ·Έλ¨ νλ¦ λΆμ μ΄λ €μμ§: λΉμμ ν¨μλ μΈλΆ μνλ₯Ό λ³κ²½νκ±°λ μμ‘΄νλ―λ‘, ν¨μ νΈμΆ νλ¦μ μΆμ νκ³ λλ²κΉ νλ κ²μ΄ μ΄λ ΅λ€.
μ°Έμ‘° ν¬λͺ μ± μ¬λ‘
μΈλΆ μνμ μμ‘΄νλ©΄ μ°Έμ‘° ν¬λͺ μ±μ΄ κΉ¨μ§ μ μλ€.
let multiplier = 2;
function multiply(x) {
return x * multiplier; // μΈλΆ λ³μ multiplierμ μμ‘΄
}
console.log(multiply(5)); // 10
multiplier = 3;
console.log(multiply(5)); // 15 ( κ°μ μ
λ ₯μ λ€λ₯Έ μΆλ ₯)
var c = 3
function sideeffect_type0(a, b) {
console.log(a + b + c)
}
sideefect_type0(1, 2) // 6
var c = 5
sideefect_type0(1, 2) // 8
ν΄κ²°
- μ°Έμ‘° ν¬λͺ μ±μ μ μ§νλ €λ©΄ ν¨μ λ΄λΆμμ μΈλΆ μνλ₯Ό μ°Έμ‘°νμ§ μμμΌ νλ€.
function multiply(x, y) {
return x * y; // μΈλΆ λ³μ μμ΄ λ΄λΆ μνλ‘λ§ μ²λ¦¬
}
console.log(multiply(5, 2)); // 10
console.log(multiply(5, 2)); // 10 (μΌκ΄λ μΆλ ₯)
function sideeffect_type0(a, b, c) {
console.log(a + b + c);
}
sideeffect_type0(1, 2, 3); // 6
sideeffect_type0(1, 2, 5); // 8
μ¬μ΄λ μ΄ννΈ(Side effect, λΆμν¨κ³Ό) μ¬λ‘
λΆμ ν¨κ³Όκ° μλ ν¨μλ μΈλΆ μνλ‘ λ³κ²½νλ―λ‘ λλ²κΉ μ΄ μ΄λ €μμ§λ€.(Difficult to Reason)
var object = {name: 'CheonSang', age: 28}
function sideEffect_type1() {
object.name = 'CheonHa'
}
sideEffect_type1()
console.log(object) // { name: 'CheonHa', age: 28 }
1. sideEffect_type1 ν¨μλ ν¨μκ° μΈλΆ κ°μ²΄ objectλ₯Ό μ§μ λ³κ²½νμ¬ Side-Effectλ₯Ό μΌμΌν΄.
var object = { name: 'CheonSang', age: 28 }
function sideEffect_type2(object) {
object.name = 'CheonJung'
}
sideEffect_type2(object)
console.log(object)
2. νλΌλ―Έν°λ₯Ό ν΅ν΄ κ°μ²΄λ₯Ό μ λ¬ λ°μ `sideEffect_type2` ν¨μκ° κ°μ²΄ `object`μ `name` μμ±μ λ³κ²½νκ³ μλ€.
μμ 1λ²λ³΄λ€λ λ«μ§λ§ μ¬μ ν Side-Effectλ₯Ό μΌμΌν€κ³ λ°ν κ° μμ΄ νλΌλ―Έν° κ°μ²΄λ₯Ό λ³κ²½νλ κ²μ λ무 λͺ μμ μ΄μ§κ° μλ€.
var object = { name: 'CheonSang', age: 28 }
function sideEffect_type3(object) {
var copied = object
copied.name = 'CheonHa'
return copied
}
var manipulated = sideEffect_type3(object)
console.log(manipulated)
console.log(object)
manipulated == object
3. 2λ²μμμ λ무 λͺ μμ μ΄μ§ μλ λ¬Έμ λ ν΄κ²°λμμ§λ§ μ¬μ ν νλΌλ―Έν° κ°μ²΄κ° λ°λκ³ λ°κΎΌ κ°μ²΄κ° νλΌλ―Έν° κ°μ²΄μ λμΌνλ€. μ¬μ ν Side-Effectκ° λ°μνλ λΉμμ ν¨μμ΄λ€. μΈλΆ μνμΈ `object`κ° λ³κ²½λλ―λ‘ ν¨μκ° μ°Έμ‘° ν¬λͺ μ±μ κ°μ§μ§ μλλ€.
ν΄κ²°
- ν¨μκ° μΈλΆ μνλ₯Ό μ§μ λ³κ²½νμ§ μλλ‘ λΆλ³μ±(Immutability)μ μ μ§νλ€.
var object = { name: 'CheonSang', age: 28 }
function sideEffect_type3(object) {
var copied = { ...object }
copied.name = 'CheonHa' // 볡μ¬λ κ°μ²΄μ name μμ±λ§ λ³κ²½
return copied
}
var manipulated = sideEffect_type3(object)
console.log(manipulated) // { name: 'CheonHa', age 28 }
console.log(object) // { name: 'CheonSang', age: 28 } (μλ³Έ κ°μ²΄λ λ³κ²½λμ§ μμ)
console.log(manipulated == object) // false (μλ‘ λ€λ₯Έ κ°μ²΄)
- `{ ...object }λ₯Ό μ¬μ©νμ¬ κ°μ²΄λ₯Ό μμ λ³΅μ¬ ν ν, 볡μ¬λ κ°μ²΄μ μμ±λ§ λ³κ²½νλ€.
- μ΄μ `manipulated`μ `object`λ μλ‘ λ€λ₯Έ κ°μ²΄λ₯Ό κ°λ₯΄ν€λ―λ‘ `manipulated == object`λ `false`μ΄λ€.
- μλ³Έ κ°μ²΄λ λ³κ²½λμ§ μκ³ , μλ‘μ΄ κ°μ²΄λ§ λ³κ²½λλ€.
var object = { name: 'CheonSang', age: 28 }
function no_sideEffect(object) {
var copied = Object.assign({}, object)
copied.name = 'CheonHa'
return copied
}
var manipulated = no_sideEffect(object)
console.log(manipulated)
console.log(object)
manipulated == object
- `Object.assign({}, object)`λ μλ³Έ κ°μ²΄μ μμ 볡μ¬λ³Έμ λ§λ λ€.
- 볡μ¬λ κ°μ²΄ (`copied`)μ `name`μμ±μ λ³κ²½νμΌλ―λ‘, μλ³Έ κ°μ²΄(`object`)μλ μν₯μ μ£Όμ§ μλλ€.
- μλ³Έ κ°μ²΄μ μλ‘μ΄ κ°μ²΄λ μλ‘ λ€λ₯Έ μ°Έμ‘°λ₯Ό κ°μ§λ―λ‘ `manipulated == object`λ `false`μ΄λ€.
Reactμμλ Immutability λΆλ³μ±μ΄ λ§€μ° μ€μνλ€.
Reactκ° λ¦¬λ λλ₯Ό μν μν λ³κ²½μ κΈ°μ€μ "κ°μ²΄ μ£Όμμ λ³κ²½"μΌλ‘ μΈμ§νκΈ° λλ¬Έμ΄λ€.
λ°λΌμ λΆλ³μ±μ μ μ§νλ©΄ μνκ° λ³κ²½λ κ²½μ° μλ‘μ΄ μ£Όμλ₯Ό κ°λ₯΄ν€κΈ° λλ¬Έμ Reactλ μνκ° λ³κ²½λμμμ μ½κ² κ°μ§ν μ μλ€.
μμ 볡μ¬(Shallow Copy) vs κΉμ 볡μ¬(Deep Copy)
- μμ 볡μ¬(Shallow Copy)
μμ 볡μ¬λ 1κ³μΈ΅λ§ 볡μ¬(κ°μ²΄μ μ΅μμ μμ±)νκ³ κ·Έ μμ±λ€μ΄ κ°λ₯΄ν€λ μ°Έμ‘° νμ (κ°μ²΄, λ°°μ΄)μ λμΌν μ°Έμ‘°λ₯Ό κ°μ§λ€.
μ¦, μ€μ²©λ κ°μ²΄λ λ°°μ΄μ μλ³Έκ³Ό 볡μ¬λ³Έμ΄ λμΌν κ°μ²΄λ₯Ό μ°Έμ‘°νκ² λλ€.
var object = {
name: 'CheonSang',
age: 28,
address: {
location: 'Seoul',
}
}
var shallowCopy = Object.assign({}, object); // μμ 볡μ¬
shallowCopy.name = 'CheonHa'; // μ΅μμ μμ±μ 볡μ¬λ³Έμλ§ μν₯μ μ€λ€.
console.log(object); // { name: 'CheonSang', age: 28, address: { location: 'Seoul' } }
console.log(shallowCopy); // { name: 'CheonHa', age: 28, address: { location: 'Seoul'} }
object.address.location = 'GyeonGi'; // μ€μ²©λ κ°μ²΄λ μλ³Έκ³Ό 볡μ¬λ³Έμ΄ λμΌν μ°Έμ‘°λ₯Ό κ°μ§.
console.log(object); // { name: 'CheonSang', age: 28, address: { location: 'GyeongGi' } }
console.log(shallowCopy); // { name: 'CheonHa', age: 28, address: { location: 'GyeongGi' } }
- κΉμ 볡μ¬(Deep Copy)
κΉμ 볡μ¬λ λͺ¨λ κ³μΈ΅μ κ°μ²΄λ₯Ό μλ‘μ΄ κ°μ²΄λ‘ 볡μ¬νλ λ°©μ. μλ³Έ κ°μ²΄μ 볡μ¬λ κ°μ²΄κ° μμ ν λ 립μ μΈ κ΅¬μ‘°λ₯Ό κ°μ§λ©°, μ€μ²©λ κ°μ²΄κΉμ§ μλ‘ λ³΅μ¬λλ€.
- μ΄λ €μ΄ λ°©λ²: typeofλ₯Ό νμ©ν μ¬κ·ν¨μ μ§μ κ°λ°
- κ°λ¨ν λ°©λ² `JSON.stringify`μ `JSON.parse`λ₯Ό μ¬μ©νλ λ°©λ²: Stringifyνμ¬ Object→StringμΌλ‘ λ§λ€μλ€κ° λ€μ μμΌλ‘ String → Objectλ‘ λ³ν
var object = {
name: 'CheonSang',
age: 28,
address: {
location: 'Seoul',
}
}
var deepCopy = JSON.parse(JSON.stringify(object)); // κΉμ 볡μ¬
deepCopy.name = 'CheonHa' // μ΅μμ μμ±μ 볡μ¬λ³Έμλ§ μν₯μ μ€λ€.
console.log(object); // { name: 'CheonSang', age: 28, address: { location: 'Seoul' } }
console.log(deepCopy); // { name: 'CheonHa', age: 28, address: { location: 'Seoul' } }
object.address.location = 'GyeongGi' // μ€μ²©λ κ°μ²΄λ λ
립μ μΈ μ°Έμ‘°λ₯Ό κ°μ§.
console.log(object); // { name: 'CheonSang', age: 28, address: { location: 'GyeongGi' } }
console.log(deepCopy); // { name: 'CheonHa', age: 28, address: { location: 'Seoul' } }
βΉοΈμ°Έκ³
[ASAC 6κΈ° κ°μμλ£]
'π»DEV-STUDY > JavaScript' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
JavaScript ν¨μ λ΄ thisμ λ©μλ λ΄ this μ°¨μ΄ (1) | 2024.09.09 |
---|---|
JavaScript ν¨μ μμ± λ°©λ² (1) | 2024.09.08 |
μλ°μ€ν¬λ¦½νΈ μμ§μ μν λ°©μ = ν¨μ μ€ν μ리 (0) | 2024.09.05 |
JavaScript λ³μ, ν¨μ μ μ λ° μ¬μ© (0) | 2024.09.05 |
μλ°μ€ν¬λ¦½νΈ λ°νμκ³Ό μλ°μ€ν¬λ¦½νΈ μμ§μ λμ μ리 (0) | 2024.08.19 |