Skip to content

Latest commit

Β 

History

History
596 lines (460 loc) Β· 25.3 KB

File metadata and controls

596 lines (460 loc) Β· 25.3 KB

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν•¨μˆ˜(function)λŠ” 맀우 νŠΉλ³„ν•œ μ‘΄μž¬μž…λ‹ˆλ‹€. μžμ„Ένžˆ μ•Œμ•„λ΄…μ‹œλ‹€!

ν•¨μˆ˜(Function)

ν•¨μˆ˜λŠ” 이름과 λ§€κ°œλ³€μˆ˜λ₯Ό κ°–κ³ , ν•„μš”ν•œ λ•Œμ— ν˜ΈμΆœν•˜μ—¬ μ½”λ“œ 블둝에 μž‘μ„±ν•œ 문듀을 μΌκ΄„μ μœΌλ‘œ μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

즉, νŠΉμ • μž‘μ—…μ„ μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ ν•„μš”ν•œ λ¬Έ(statement)의 집합을 μ •μ˜ν•œ μ½”λ“œ 블둝이 ν•¨μˆ˜μž…λ‹ˆλ‹€. 이 ν•¨μˆ˜λŠ” μ•„λž˜μ™€ 같은 κΈ°λŠ₯을 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  1. 반볡적으둜 μž‘μ„±λ˜λŠ” μ½”λ“œλ₯Ό ν•¨μˆ˜λ‘œ μ •μ˜ν•˜μ—¬ μž¬μ‚¬μš©
    • ν•¨μˆ˜μ˜ μ•„μ΄λ΄ν‹°ν‹°λŠ” μž¬μ‚¬μš©μ„±μ— μžˆμŠ΅λ‹ˆλ‹€.
  2. 객체 생성
  3. 객체의 ν–‰μœ„ μ •μ˜(λ©”μ„œλ“œλ‘œ λ™μž‘)
  4. 정보 은닉
  5. ν΄λ‘œμ €
  6. λͺ¨λ“ˆν™”

κΈ°λŠ₯을 보면 μ΄μƒν•˜μ£ ? 마치 ν•¨μˆ˜κ°€ 객체처럼 쓰일 수 μžˆλŠ” 것 κ°™μ•„μš”. λ†€λžκ²Œλ„ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν•¨μˆ˜λŠ” ν˜ΈμΆœν•  수 μžˆλŠ” 객체(First-Class Object)λ‘œμ„œ 일급 객체라고 λΆˆλ¦½λ‹ˆλ‹€. λ³€μˆ˜λ‚˜ 객체, λ°°μ—΄μ˜ ν”„λ‘œνΌν‹°(λ©”μ„œλ“œ)둜 μ •μ˜ν•  수 있고, λ‹€λ₯Έ ν•¨μˆ˜μ— μ „λ‹¬ν•˜λŠ” μΈμˆ˜λ‘œλ„ μ‚¬μš©ν•  수 있으며, λ‹€λ₯Έ ν•¨μˆ˜μ˜ λ°˜ν™˜κ°’μ΄ 될 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

그런데, 일급 객체가 뭐죠?

일급 객체

ν•¨μˆ˜λŠ” 일반 객체가 μ•„λ‹ˆλΌ 일급 객체(First-Class Object) 둜 μ·¨κΈ‰λ©λ‹ˆλ‹€.

  • μ•„λž˜μ™€ 같은 쑰건을 λ§Œμ‘±ν•˜λ©΄ 일급 객체라고 ν•΄μš”.
    1. 무λͺ… λ¦¬ν„°λŸ΄λ‘œ 생성(λŸ°νƒ€μž„μ— 생성이 κ°€λŠ₯ν•˜λ‹€λŠ” μ΄μ•ΌκΈ°μ—μš”)ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    2. λ³€μˆ˜, 각쒅 자료ꡬ쑰(Object, Array, Set, Map λ“±)에 μ €μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    3. ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜(Parameter)둜 전달할 수 μžˆμŠ΅λ‹ˆλ‹€.
    4. ν•¨μˆ˜μ˜ λ°˜ν™˜(return) κ°’μœΌλ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 예제 μ½”λ“œλ₯Ό 보면 더 μ •ν™•νžˆ μ•Œκ² μ£ ?
    // 1번, 2번 쑰건에 μΆ©μ‘±λ©λ‹ˆλ‹€.
    const increase = function (num) {
      return ++num;
    }
    console.log(increase);                // Ζ’ (num) { return ++num; }
    console.log(increase(3));             // 4
    
    
    // 3번 쑰건에 μΆ©μ‘±λ©λ‹ˆλ‹€.
    const predicates = { increase };
    console.log(predicates);              // {increase: Ζ’}
    console.log(predicates.increase(3));  // 4
    
    // 3번, 4번 쑰건에 μΆ©μ‘±λ©λ‹ˆλ‹€.
    function makeCounter(predicates) {
      let num = 0;
    
      return function() {
        num = predicates(num);
        return num;
      };
    }
    
    const increaser = makeCounter(predicates.increase);
    console.log(increaser());             // 1
    console.log(increaser());             // 2

ν•¨μˆ˜λŠ” 일급 κ°μ²΄λΌλŠ” 것은 ν•¨μˆ˜λ₯Ό 객체와 λ™μΌν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€λŠ” μ˜λ―Έμž…λ‹ˆλ‹€. 즉, ν•¨μˆ˜λŠ” 값을 κ°€μš©ν•  수 μžˆλŠ” 곳이라면 λ¦¬ν„°λŸ΄λ‘œ μ •μ˜ν•  수 있고 λŸ°νƒ€μž„μ— ν•¨μˆ˜ 객체둜 ν‰κ°€λ˜λŠ” 것이죠.

ν•¨μˆ˜ 객체와 일반 κ°μ²΄λŠ” μ•„λž˜μ™€ 같은 차이가 μžˆμŠ΅λ‹ˆλ‹€.

  1. μ†Œκ΄„ν˜Έ(())λ₯Ό μ‚¬μš©ν•œ 호좜인데, 일반 κ°μ²΄λŠ” 호좜이 λΆˆκ°€λŠ₯ν•˜μ§€λ§Œ ν•¨μˆ˜ κ°μ²΄λŠ” ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  2. ν•¨μˆ˜ κ°μ²΄μ—λŠ” 일반 객체에 μ—†λŠ” ν•¨μˆ˜ 고유 ν”„λ‘œνΌν‹°κ°€ μ‘΄μž¬ν•©λ‹ˆλ‹€.

ν•¨μˆ˜λ„ 일반 객체처럼 ν”„λ‘œνΌν‹°λ₯Ό μ†Œμœ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 즉, Object.getOwnPropertyDescriptorsλ₯Ό μ‚¬μš©ν•  수 있죠. ν•¨μˆ˜ 객체가 μ†Œμœ ν•œ ν”„λ‘œνΌν‹°λ₯Ό μ‚΄νŽ΄λ³ΌκΉŒμš”?

TODO : callee ν”„λ‘œνΌν‹° λˆ„λ½λ˜μ—ˆμŒ 2021-10-01

  • arguments ν”„λ‘œνΌν‹°
    • arguments κ°μ²΄λŠ” ν•¨μˆ˜ 호좜 μ‹œ μ „λ‹¬λœ 인수(argument)λ“€μ˜ 정보λ₯Ό λ‹΄κ³  μžˆλŠ” 순회 κ°€λŠ₯(Iterable)ν•œ μœ μ‚¬ λ°°μ—΄ κ°μ²΄μž…λ‹ˆλ‹€.
    • ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ§€μ—­ λ³€μˆ˜μ²˜λŸΌ μ‚¬μš©λ˜λ©° μ™ΈλΆ€μ—μ„œλŠ” μ°Έμ‘°ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
    • ES3λΆ€ν„° ν‘œμ€€μ—μ„œ νμ§€λ˜μ–΄ μ‚¬μš©μ΄ ꢌμž₯λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
    • μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜μ™€ 인수의 κ°œμˆ˜κ°€ μΌμΉ˜ν•˜λŠ”μ§€ ν™•μΈν•˜μ§€ μ•Šμ•„ μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
      • μ§€μ •λœ κ°œμˆ˜λ³΄λ‹€ 적은 경우 : λ§€κ°œλ³€μˆ˜λŠ” undefined둜 μ΄ˆκΈ°ν™”λ©λ‹ˆλ‹€.
      • μ§€μ •λœ κ°œμˆ˜λ³΄λ‹€ λ§Žμ€ 경우 : μ•”λ¬΅μ μœΌλ‘œ arguments 객체에 μˆœμ„œλŒ€λ‘œ μ €μž₯(순회 κ°€λŠ₯ν•œ μœ μ‚¬ λ°°μ—΄ κ°μ²΄μ΄λ―€λ‘œ)λ©λ‹ˆλ‹€.
      • μ΄λŸ¬ν•œ 이유둜 κ°€λ³€ 인자 ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•  λ•Œ μœ μš©ν•©λ‹ˆλ‹€.
    • 단, μœ μ‚¬ λ°°μ—΄ κ°μ²΄λŠ” 배열이 μ•„λ‹ˆλ―€λ‘œ λ°°μ—΄ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•  수 μ—†μœΌλ‚˜ μ•„λž˜μ˜ λ°©λ²•μœΌλ‘œ κ°„μ ‘ ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.
      1. Function.prototype.call, Function.prototype.apply μ‚¬μš©ν•˜κΈ°. μ°Έμ‘°1
      function sum(){
        // const array = Array.prototype.slice.apply(arguments);
        const array = Array.prototype.slice.call(arguments);
        return array.reduce(function (pre, cur){
          return pre + cur;
        }, 0);
      }
      console.log(sum(1, 2, 3, 4, 5));  // 15
      1. ES6의 Rest νŒŒλΌλ―Έν„°
      function sum(...args){
        return args.reduce((pre, cur) => pre + cur, 0);
      }
      console.log(sum(1, 2, 3, 4, 5));  // 15

  • caller ν”„λ‘œνΌν‹°
    • λΉ„ν‘œμ€€ ν”„λ‘œνΌν‹°λ‘œ ν•¨μˆ˜ μžμ‹ μ„ ν˜ΈμΆœν•œ ν•¨μˆ˜λ₯Ό κ°€λ¦¬ν‚΅λ‹ˆλ‹€.

  • length ν”„λ‘œνΌν‹°
    • ν•¨μˆ˜λ₯Ό μ •μ˜ν•  λ•Œ μ„ μ–Έν•œ λ§€κ°œλ³€μˆ˜μ˜ 개수λ₯Ό κ°€λ¦¬ν‚΅λ‹ˆλ‹€.
    • arguments 객체의 length ν”„λ‘œνΌν‹°μ™€ ν•¨μˆ˜ 객체의 length ν”„λ‘œνΌν‹°μ˜ 값은 λ‹€λ₯Ό 수 μžˆμŠ΅λ‹ˆλ‹€.
      • μ „μžμ˜ 경우 인자(argument)의 개수, ν›„μžμ˜ 경우 λ§€κ°œλ³€μˆ˜(parameter)의 개수λ₯Ό 가리킀기 λ–„λ¬Έμ΄μ§€μš”.

  • name ν”„λ‘œνΌν‹°
    • ES6μ—μ„œ ν‘œμ€€μ΄ λ˜μ—ˆμœΌλ©° ν•¨μˆ˜ 이름을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€. ES5와 ES6의 λ™μž‘μ΄ μ„œλ‘œ λ‹€λ¦…λ‹ˆλ‹€.
    • 읡λͺ… ν•¨μˆ˜ ν‘œν˜„μ‹μ˜ 경우 ES5λŠ” 빈 λ¬Έμžμ—΄μ„, ES6λŠ” ν•¨μˆ˜ 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” μ‹λ³„μžλ₯Ό κ°’μœΌλ‘œ κ°–μŠ΅λ‹ˆλ‹€.

  • proto μ ‘κ·Όμž ν”„λ‘œνΌν‹°
    • [[Prototype]] λ‚΄λΆ€ 슬둯이 κ°€λ¦¬ν‚€λŠ” ν”„λ‘œν† νƒ€μž… 객체에 μ ‘κ·Όν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•©λ‹ˆλ‹€.

  • prototype ν”„λ‘œνΌν‹°
    • μƒμ„±μž ν•¨μˆ˜λ‘œ ν˜ΈμΆœν•  수 μžˆλŠ” 객체둜 constructor만이 μ†Œμœ ν•©λ‹ˆλ‹€.
    • 일반 객체와 μƒμ„±μž ν•¨μˆ˜λ‘œ ν˜ΈμΆœν•  수 μ—†λŠ” non-constructorλŠ” prototype ν”„λ‘œνΌν‹°κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
      • 즉, ν•¨μˆ˜κ°€ 객체λ₯Ό μƒμ„±ν•˜λŠ” μƒμ„±μž ν•¨μˆ˜λ‘œ 호좜될 λ•Œ, μƒμ„±μž ν•¨μˆ˜κ°€ 생성할 μΈμŠ€ν„΄μŠ€μ˜ ν”„λ‘œν† νƒ€μž… 객체λ₯Ό κ°€λ¦¬ν‚€λŠ” κ±°μ£ .

__proto__와 [[Prototype]]에 λŒ€ν•΄μ„œλŠ” ν”„λ‘œν† νƒ€μž… νŽ˜μ΄μ§€λ₯Ό μ°Έκ³ ν•΄μ£Όμ„Έμš”.


ν•¨μˆ˜ μ •μ˜

ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜λŠ” 방식은 λ„€ κ°€μ§€(ES6μ—μ„œ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€)둜 λΆ„λ₯˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  1. ν•¨μˆ˜ μ„ μ–Έλ¬Έ(Function Declaration) : function ν‚€μ›Œλ“œμ™€ ν•¨μˆ˜λͺ…, λ§€κ°œλ³€μˆ˜ λͺ©λ‘, ν•¨μˆ˜ λͺΈμ²΄λ‘œ κ΅¬μ„±λ©λ‹ˆλ‹€.

    function sum(a, b){
      return a + b;
    }
    
    console.log(sum(1, 2)); // 3
    • ν•¨μˆ˜ 선언문은 ν•¨μˆ˜λͺ…을 μƒλž΅ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
    • μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν•¨μˆ˜λŠ” λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž…μ„ κΈ°μˆ ν•˜μ§€ μ•ŠμœΌλ©°, λ§€κ°œλ³€μˆ˜λ₯Ό λ„˜κΈ°μ§€ μ•ŠμœΌλ©΄ undefined둜 μ„ μ–Έλ©λ‹ˆλ‹€.
      function sum(a, b){
        return a + b;
      }
      console.log(sum());   // NaN
    • ν•¨μˆ˜ λͺΈμ²΄λŠ” ν•¨μˆ˜ 호좜 μ‹œ μ‹€ν–‰λ˜λŠ” λ¬Έλ“€μ˜ μ§‘ν•©λ‹™λ‹ˆλ‹€. μ€‘κ΄„ν˜Έ({})둜 감싸지며 return 문으둜 ν•¨μˆ˜ μ‹€ν–‰μ˜ κ²°κ³Ό(return value)λ₯Ό λ°˜ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  2. ν•¨μˆ˜ ν‘œν˜„μ‹(Function Expression) : ν•¨μˆ˜ λ¦¬ν„°λŸ΄ λ°©μ‹μœΌλ‘œ ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜κ³  λ³€μˆ˜μ— ν• λ‹Ήν•©λ‹ˆλ‹€. μ’…λ₯˜κ°€ 두 κ°€μ§€ μ‘΄μž¬ν•˜λŠ”λ°, 예제둜 μ‚΄νŽ΄λ΄…λ‹ˆλ‹€.

    • κΈ°λͺ… ν•¨μˆ˜ ν‘œν˜„μ‹ : ν•¨μˆ˜λͺ…을 μ§€μ •ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€.
      const foo = function sum(a, b){
        return a + b;
      }
      
      console.log(foo(1, 2)); // 3
      console.log(sum(1, 2)); // ReferenceError: multiply is not defined
      • 이처럼 λ³€μˆ˜μ— ν• λ‹Ήν•  수 μžˆλŠ” μ΄μœ λŠ” ν•¨μˆ˜κ°€ 일급 객체둜 ν‰κ°€λ˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. ν•΄λ‹Ή λ³€μˆ˜λŠ” μ›μ‹œ 값이 μ•„λ‹ˆλΌ ν• λ‹Ήλœ ν•¨μˆ˜λ₯Ό κ°€λ¦¬ν‚€λŠ” 참쑰값을 μ €μž₯ν•˜λ©°, ν•¨μˆ˜λͺ…이 μ•„λ‹Œ λ³€μˆ˜λͺ…μœΌλ‘œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.
      • ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…κ³Ό μ—°κ΄€λœ ν•­λͺ©μ΄λ―€λ‘œ μ•„λž˜μ—μ„œ μžμ„Ένžˆ λ‹€λ£Ήλ‹ˆλ‹€.
    • 읡λͺ… ν•¨μˆ˜ ν‘œν˜„μ‹ : ν•¨μˆ˜λͺ…을 μƒλž΅ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€.
      // ES5의 ν•¨μˆ˜ ν‘œν˜„μ‹
      const bar = function(a, b){
        return a + b;
      }
      
      const foo = bar;
      
      console.log(bar(1, 2)); // 3
      console.log(foo(1, 2)); // 3
  3. Function μƒμ„±μž ν•¨μˆ˜ : μ‚¬μš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€!

    const sum = new Function('a', 'b', 'return a + b');
    
    console.log(sum); // 3
    • 그리고 ν˜„μž¬ λͺ¨λ˜ λΈŒλΌμš°μ €μ—μ„œλŠ” μ•„λž˜μ™€ 같은 였λ₯˜κ°€ λ°œμƒν•˜λ„€μš”! : EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src chrome://resources chrome://test 'self' 'unsafe-inline' https:".
  4. ν™”μ‚΄ν‘œ ν•¨μˆ˜ : ES6에 λ“±μž₯ν•œ μƒˆλ‘œμš΄ ν•¨μˆ˜ μ„ μ–Έ λ°©μ‹μœΌλ‘œ, function ν‚€μ›Œλ“œ λŒ€μ‹  ν™”μ‚΄ν‘œ(arrow, =>)λ₯Ό μ‚¬μš©ν•΄ 더 κ°„λž΅ν•˜κ²Œ ν‘œκΈ°ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 항상 읡λͺ… ν•¨μˆ˜λ‘œ μ •μ˜ν•©λ‹ˆλ‹€.

    // ES6의 ν™”μ‚΄ν‘œ ν•¨μˆ˜ : 읡λͺ… ν•¨μˆ˜λ‘œ μž‘μ„±ν•©λ‹ˆλ‹€.
    const bar = (a, b) => {
      return a + b;
    }
    
    console.log(bar(1, 2));  // 3
    • 문법이 쑰금 달라짐을 μ œμ™Έν•˜λ©΄ νŠΉμ΄ν•œ 점이 μ—†λŠ”λ°... λ‚΄λΆ€ λ™μž‘μ΄ 많이 λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μžμ„Έν•œ 것은 ES6의 ν•¨μˆ˜μ—μ„œ μ’€ 더 μžμ„Ένžˆ 닀뀄보죠.

ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜λŠ” 방식이 λ„€ κ°€μ§€λ‚˜ λ©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ λ°˜ν™˜ν•˜λŠ” κ²°κ³ΌλŠ” λ™μΌν•˜λ„€μš”? λŒ€μ²΄ 뭐가 λ‹€λ₯΄κΈΈλž˜ μ΄λ ‡κ²Œ λ‚˜λˆ μ§„ κ±ΈκΉŒμš”? μ—¬κΈ°μ„œ ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄ λ“±μž₯ν•©λ‹ˆλ‹€.


ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…(Function Hoisting)

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” λͺ¨λ“  선언을 ν˜Έμ΄μŠ€νŒ…ν•©λ‹ˆλ‹€!

μš°μ„  예제λ₯Ό λ΄…μ‹œλ‹€!

console.log(sum(1, 2)); // 3

function sum(a, b){
  return a + b;
}

였, μž‘λ™ν•˜λ„€μš”? 그럼 μ €ν¬λŠ” μ΄λ ‡κ²Œ 생각할 수 μžˆμŠ΅λ‹ˆλ‹€. ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜λŠ”κ΅¬λ‚˜!

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” λͺ¨λ“  선언문이 μ„ μ–Έλ˜κΈ° 이전에 μ°Έμ‘°κ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€. ν•¨μˆ˜ μ„ μ–Έλ¬ΈμœΌλ‘œ μ •μ˜λœ ν•¨μˆ˜κ°€ ν‰κ°€λ˜λŠ” 과정은 μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

  1. μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진이 μŠ€ν¬λ¦½νŠΈκ°€ λ‘œλ”©λ˜λŠ” μ‹œμ μ— μ΄ˆκΈ°ν™” ν•©λ‹ˆλ‹€.
  2. μ΄ˆκΈ°ν™”λœ ν•¨μˆ˜λ₯Ό λ³€μˆ˜ 객체(Variable Object, VO)에 μ €μž₯ν•©λ‹ˆλ‹€.

μ΄λ ‡κ²Œ ν•¨μˆ˜μ˜ μ„ μ–Έ, μ΄ˆκΈ°ν™”, 할당이 ν•œ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ΄λ£¨μ–΄μ§€λŠ” κ²ƒμž…λ‹ˆλ‹€! 그럼 λ‹Ήμ—°νžˆ ν•¨μˆ˜ μ„ μ–Έμ˜ μœ„μΉ˜μ™€ 상관 없이 μ–΄λŠ κ³³μ—μ„œλ“  호좜이 κ°€λŠ₯ν•˜μ£ .

const result = sum(1, 2);

console.log(sum(1, 2));  // ReferenceError: sum2 is not defined

const sum = function(a, b){
  return a + b;
}

κ·Έλ ‡μ§€λ§Œ ν•¨μˆ˜ ν‘œν˜„μ‹μ€ ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄ μ•„λ‹Œ λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•©λ‹ˆλ‹€. λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…μ€ ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…κ³Ό κ·Έ 과정이 λ‹€λ¦…λ‹ˆλ‹€. μ•„λž˜λ₯Ό λ³ΌκΉŒμš”?

  1. ν•¨μˆ˜ ν‘œν˜„μ‹μ€ λŸ°νƒ€μž„(Runtime)에 ν•΄μ„λ˜κ³  μ‹€ν–‰λ˜λ―€λ‘œ λ³€μˆ˜ 생성과 μ΄ˆκΈ°ν™”, 할당이 λΆ„λ¦¬λ˜μ–΄ μ§„ν–‰λ©λ‹ˆλ‹€.
  2. ν˜Έμ΄μŠ€νŒ…λœ λ³€μˆ˜λŠ” undefined둜 μ΄ˆκΈ°ν™”λ©λ‹ˆλ‹€.
  3. μ‹€μ œλ‘œ κ°’μ˜ 할당은 ν• λ‹Ήλ¬Έμ—μ„œ μ΄λ£¨μ–΄μ§‘λ‹ˆλ‹€!

ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…μ€ ν•¨μˆ˜ 호좜 전에 λ°˜λ“œμ‹œ ν•¨μˆ˜λ₯Ό μ„ μ–Έν•΄μ•Ό λœλ‹€λŠ” κ·œμΉ™μ„ λ¬΄μ‹œν•˜κΈ° λ•Œλ¬Έμ— μ½”λ“œμ˜ ꡬ쑰적 결함이 λ°œμƒν•  수 μžˆμœΌλ―€λ‘œ ν•¨μˆ˜ ν‘œν˜„μ‹μ„ μ‚¬μš©ν•˜λ„λ‘ ꢌμž₯ν•©λ‹ˆλ‹€.


ν•¨μˆ˜ 호좜

ν•¨μˆ˜λ₯Ό κ°€λ¦¬ν‚€λŠ” μ‹λ³„μžμ™€ ν•¨μˆ˜ 호좜 μ—°μ‚°μž(())둜 ν˜ΈμΆœν•©λ‹ˆλ‹€.

μš°λ¦¬λŠ” λ§Žμ€ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄ μ™”μŠ΅λ‹ˆλ‹€. μ •ν™•ν•œ λͺ…칭을 λͺ°λΌλ„ μƒλ‹Ήνžˆ μ§κ΄€μ μœΌλ‘œ λ‹€κ°€μ˜€λŠ” ν˜•νƒœμ΄μ£ . κ·Έλ¦ΌλΆ€ν„° λ³ΌκΉŒμš”?



λ§€κ°œλ³€μˆ˜λŠ” ν•¨μˆ˜ λͺΈμ²΄ λ‚΄λΆ€μ—μ„œ λ³€μˆ˜μ™€ λ™μΌν•˜κ²Œ μ·¨κΈ‰λ©λ‹ˆλ‹€. λ§€κ°œλ³€μˆ˜(Parameters)λŠ” 인수(Arguments)에 μ—°κ²°λ©λ‹ˆλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 이λ₯Ό μ²˜λ¦¬ν•˜λŠ” 방식이 λ‹€λ₯Έ 언어와 λ‹¬λΌμš”. λ‹€λ₯Έ μ–Έμ–΄μ—μ„œλŠ” λ§€κ°œλ³€μˆ˜μ™€ μΈμˆ˜κ°€ 1:1 λŒ€μ‘ λ˜κ±°λ‚˜, ν•„μš”ν•œ 인수λ₯Ό λ„˜κ²¨μ£Όμ§€ μ•ŠμœΌλ©΄ μ—λŸ¬λ₯Ό λƒ…λ‹ˆλ‹€.

그에 λ°˜ν•΄ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” μ•”λ¬΅μ μœΌλ‘œ λ§€κ°œλ³€μˆ˜κ°€ μƒμ„±λ˜κ³ , undefined둜 μ΄ˆκΈ°ν™”λ˜μ–΄ ν•¨μˆ˜ 호좜 μ‹œ μž…λ ₯ν•œ 인수의 μˆœμ„œλŒ€λ‘œ ν• λ‹Ήλ˜λŠ” ν˜•νƒœμž…λ‹ˆλ‹€.

νŠΉμ§•μ„ λ‚˜μ—΄ν•΄λ³΄λ©΄ μ•„λž˜μ™€ κ°™μ•„μš”.

  1. ν•¨μˆ˜λŠ” λ§€κ°œλ³€μˆ˜μ™€ 인수의 κ°œμˆ˜κ°€ μΌμΉ˜ν•˜λŠ”μ§€ μ²΄ν¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
  • μΈμˆ˜κ°€ ν• λ‹Ήλ˜μ§€ μ•Šμ€ λ§€κ°œλ³€μˆ˜λŠ” undefinedκ°€ λ©λ‹ˆλ‹€!
    function sum(a, b){
      console.log(a, b);      // 1, undefined
      return a + b;
    }
    
    console.log(sum(1));      // NaN
  1. μΈμˆ˜κ°€ λ§€κ°œλ³€μˆ˜λ³΄λ‹€ λ§Žμ€ 경우 μ—λŸ¬ 없이 λ¬΄μ‹œλ©λ‹ˆλ‹€.
    funtion sum(a, b){
      return a + b;
    }
    
    console.log(sum(1, 2, 3));  // 3
  2. 였, κ·Έλ ‡λ‹€κ³  μ΄ˆκ³Όν•œ μΈμˆ˜κ°€ μ‚¬λΌμ§€λŠ” 것은 μ•„λ‹™λ‹ˆλ‹€. νŠΉμ΄ν•˜κ²Œλ„ argumentsλΌλŠ” 객체에 ν”„λ‘œνΌν‹°λ‘œ λ³΄κ΄€λ˜κΈ° λ•Œλ¬Έμ΄μ£ .
    function sum(a, b{
      console.log(arguments);
      // Arguments(3)Β [1, 2, 3, caljames: Ζ’, Symbol(Symbol.iterator): Ζ’]
    }
    
    sum(1, 2, 3);
    • arguments κ°μ²΄λŠ” κ°€λ³€ 인자 ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•  λ•Œ μœ μš©ν•©λ‹ˆλ‹€. 뒀에 μžμ„Ένžˆ λ‹€λ£¨λ‹ˆ μ•ˆμ‹¬ν•˜μ„Έμš”!
  3. μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” λ§€κ°œλ³€μˆ˜ νƒ€μž…μ„ 사전에 μ§€μ •ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
    • 그렇기에 ν•„μ—°μ μœΌλ‘œ μ μ ˆν•œ μΈμˆ˜κ°€ μ „λ‹¬λ˜μ—ˆλŠ”μ§€ 확인해야 ν•©λ‹ˆλ‹€. 이λ₯Ό λ¬΄μ‹œν•˜λ©΄ ν•¨μˆ˜ ν˜ΈμΆœμ— λŒ€ν•œ μ—λŸ¬κ°€ λŸ°νƒ€μž„μ— λ°œμƒν•˜κ²Œ λ˜λ‹ˆκΉŒμš”.
    • 기본적으둜 단좕 평가λ₯Ό μ‚¬μš©ν•˜μ—¬ 기본값을 많이 ν• λ‹Ήν–ˆμœΌλ‚˜, ES6μ—μ„œλŠ” λ§€κ°œλ³€μˆ˜μ— 기본값을 μ§€μ •ν•  수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
  4. λ§€κ°œλ³€μˆ˜μ˜ κ°œμˆ˜μ—λŠ” μ œν•œμ΄ μ—†μŠ΅λ‹ˆλ‹€. 말도 μ•ˆλ˜μ§€λ§Œ 객체 ν˜•νƒœλ‘œ κ΄€λ¦¬λ˜λ‹ˆκΉŒμš”. λ¬Όλ‘  λ§€κ°œλ³€μˆ˜μ˜ κ°œμˆ˜λŠ” μ΅œμ†Œν•œμœΌλ‘œ ν•΄μ•Όν•˜λ©°, μ΅œλŒ€λ‘œλŠ” 3κ°œκΉŒμ§€ ꢌμž₯ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.
    • λ§Œμ•½ λ§Žμ€ λ§€κ°œλ³€μˆ˜λ₯Ό λ„˜κ²¨μ•Ό ν•˜λŠ” 상황이라면, 객체 ν˜•νƒœλ‘œ μ „λ‹¬ν•΄λ³΄μ„Έμš”!
      function sum(expr){
        return expr.a + expr.b + expr.c + expr.d + expr.e;
      }
      
      console.log(sum({a:1, b:2, c:3, d:4, e:5}));
      • 단, 객체λ₯Ό 인수둜 μ‚¬μš©ν•˜λ©΄ μ°Έμ‘° 값을 λ°”λΌλ³΄κ²Œ λ˜λ―€λ‘œ 원본 객체에 λ³€ν˜•μ΄ κ°€ν•΄μ§€λ‹ˆ μ£Όμ˜ν•΄μ£Όμ„Έμš”.

였, μ€‘μš”ν•œ λ‚΄μš©μ΄ λ‚˜μ™”λ„€μš”. λ§€κ°œλ³€μˆ˜λ‘œ 객체λ₯Ό λ„˜κΈ°λ©΄ 원본 객체에 λ³€ν˜•μ΄ κ°€ν•΄μ§„λ‹€κ΅¬μš”? 이게 무슨 일이죠?

κ·Έλž˜λ„ λ‹€ν–‰νžˆ, μš°λ¦¬λŠ” μ›μ‹œ κ°’κ³Ό 객체가 μ–΄λ–»κ²Œ λ™μž‘ν•˜κ³  λ©”λͺ¨λ¦¬μ— ν• λ‹Ήλ˜λŠ”μ§€ μ΄ν•΄ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. κ·Έλ¦Όκ³Ό 예제λ₯Ό λ³΄λ©΄μ„œ 이 ν•¨μˆ˜ 호좜 상황을 μžμ„Ένžˆ μƒκ°ν•΄λ³ΌκΉŒμš”?


μ›μ‹œ 값인 λ³€μˆ˜ num을 λ„˜κΈ°λ©΄ λ§€κ°œλ³€μˆ˜λŠ” 값을 λ³΅μ‚¬ν•˜λ―€λ‘œ λ§€κ°œλ³€μˆ˜μ™€ μΈμˆ˜κ°€ μ„œλ‘œ λ‹€λ¦…λ‹ˆλ‹€.

객체인 λ³€μˆ˜ objλ₯Ό λ„˜κΈ°λ©΄ λ§€κ°œλ³€μˆ˜λŠ” μ°Έμ‘° 값을 λ³΅μ‚¬ν•˜λ―€λ‘œ λ§€κ°œλ³€μˆ˜μ™€ μΈμˆ˜κ°€ μ„œλ‘œ κ°™μŠ΅λ‹ˆλ‹€.


ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄μ„œ λ§€κ°œλ³€μˆ˜μ— 값을 μ „λ‹¬ν•˜λŠ” 방식을 값에 μ˜ν•œ 호좜(Call by Value), 참쑰에 μ˜ν•œ 호좜(Call by Reference)이라고 ν•©λ‹ˆλ‹€. κ²°κ΅­ λ™μž‘μ€ 값을 전달함에 μžˆμ–΄ λ™μΌν•˜μ§€λ§Œμš”. μ•„λž˜ 예제λ₯Ό λ΄…μ‹œλ‹€.

function changeVal(primitive, obj) {
  primitive += 100;
  obj.name = 'amy';
  obj.age = 16;
  console.log(primitive); // 200
}

const num = 100;
const obj = {
  name: 'james',
  age: 24
};

console.log(num);         // 100
console.log(obj);         // {name: 'james', age: 24}

changeVal(num, obj);

console.log(num);         // 100
console.log(obj);         // {name: 'amy', age: 16}

κ²°κ΅­, μ›μ‹œ κ°’ num은 변경이 λΆˆκ°€λŠ₯ν•˜λ―€λ‘œ μž¬ν• λ‹Ήμ„ 톡해 μƒˆλ‘œμš΄ μ›μ‹œ κ°’μœΌλ‘œ κ΅μ²΄ν–ˆμŠ΅λ‹ˆλ‹€. 객체 objλŠ” 변경이 κ°€λŠ₯ν•˜λ―€λ‘œ μž¬ν• λ‹Ή 없이 직접 값을 κ΅μ²΄ν–ˆμ£ . μ—¬κΈ°μ„œ μ€‘μš”ν•œ 것은 μ›μ‹œ 값을 λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬ν•˜λ©΄ μ›λ³Έμ˜ 값을 ν›Όμ†ν•˜μ§€ μ•Šμ•„ λΆ€μˆ˜ νš¨κ³Όκ°€ μΌμ–΄λ‚˜μ§€ μ•Šκ³ , κ°μ²΄λŠ” μΌμ–΄λ‚œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. λ‹Ήμ—°νžˆ 원본 객체가 ν›Όμ†λ˜λ©΄ λ§Žμ€ λ¬Έμ œκ°€ 생기겠죠? 이에 λŒ€ν•œ ν•΄κ²°μ±…μœΌλ‘œ 객체λ₯Ό λΆˆλ³€ 객체(Immutable Object) 둜 λ§Œλ“€κ±°λ‚˜, κΉŠμ€ 볡사(Deep Copy) ν•˜λŠ” 방법이 μ‘΄μž¬ν•©λ‹ˆλ‹€.

μ΄λ ‡κ²Œ μ™ΈλΆ€ μƒνƒœλ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³ , 또 μ˜μ‘΄ν•˜μ§€ μ•ŠλŠ” ν•¨μˆ˜λ₯Ό 순수 ν•¨μˆ˜λΌκ³  ν•©λ‹ˆλ‹€. 자, 또 λͺ¨λ₯΄λŠ” 단어가 λ‚˜μ™”κ΅°μš”? κΈ° μ£½μ§€ 말고 μ•„λž˜μ—μ„œ μ‚΄νŽ΄λ΄…μ‹œλ‹€!


순수 ν•¨μˆ˜, λΉ„μˆœμˆ˜ ν•¨μˆ˜

λΆ€μˆ˜ 효과(Side Effect)κ°€ μ—†λŠ” ν•¨μˆ˜λ₯Ό 순수 ν•¨μˆ˜(Pure Function), λΆ€μˆ˜ νš¨κ³Όκ°€ μžˆλŠ” ν•¨μˆ˜λ₯Ό λΉ„μˆœμˆ˜ ν•¨μˆ˜(Impure Function)라고 ν•©λ‹ˆλ‹€.

λ°”λ‘œ 예제λ₯Ό 톡해 순수 ν•¨μˆ˜, λΉ„μˆœμˆ˜ ν•¨μˆ˜λ₯Ό μ œλŒ€λ‘œ μ§šμ–΄λ΄…μ‹œλ‹€.

  • 순수 ν•¨μˆ˜ : 순수 ν•¨μˆ˜κ°€ λ°˜ν™˜ν•œ κ²°κ³Όλ₯Ό λ³€μˆ˜μ— μž¬ν• λ‹Ήν•˜λ―€λ‘œ 좔적이 μ‰½μŠ΅λ‹ˆλ‹€.

    let count = 0;
    
    // 순수 ν•¨μˆ˜
    function increase(n) {
      // μ™ΈλΆ€ μƒνƒœμ— μ˜μ‘΄μ μ΄μ§€ μ•Šκ³  μ™ΈλΆ€ μƒνƒœλ₯Ό λ³€κ²½ν•˜μ§€λ„ μ•ŠλŠ”λ‹€.
      return ++n;
    }
    
    count = increase(count);
    console.log(count); // 1
    
    count = increase(count);
    console.log(count); // 2
  • λΉ„μˆœμˆ˜ ν•¨μˆ˜ : μ™ΈλΆ€ μƒνƒœ(count)λ₯Ό λ³€κ²½ν•˜λ‹ˆ μƒνƒœ λ³€ν™”λ₯Ό μΆ”μ ν•˜κΈ° νž˜λ“€μ–΄μš”.

    let count = 0;
    
    // λΉ„μˆœμˆ˜ ν•¨μˆ˜
    function increase() {
      // μ™ΈλΆ€ μƒνƒœμ— μ˜μ‘΄ν•˜λ©° μ™ΈλΆ€ μƒνƒœλ₯Ό λ³€κ²½ν•œλ‹€.
      return ++count;
    }
    
    increase();
    console.log(count); // 1
    
    increase();
    console.log(count); // 2

λ‹Ήμ—°νžˆ, 얕은 λ³΅μ‚¬λœ 객체λ₯Ό 인수둜 λ„˜κΈ°λ©΄ μ™ΈλΆ€ μƒνƒœμ— μ˜μ‘΄ν•˜κ²Œ λ©λ‹ˆλ‹€. κ·Έλž˜μ„œ λΉ„μˆœμˆ˜ ν•¨μˆ˜κ°€ λ˜λ‹ˆ, μœ„μ—μ„œ μ–ΈκΈ‰ν•œ 해결책을 μ‚¬μš©ν•˜μ—¬ 순수 ν•¨μˆ˜λ‘œ μž‘μ„±ν•˜κΈ° λ°”λžλ‹ˆλ‹€.

λ§ˆμ§€λ§‰μœΌλ‘œ, 순수 ν•¨μˆ˜μ˜ νŠΉμ§•μ„ μ‚΄νŽ΄λ³ΌκΉŒμš”?

  1. λΆ€μˆ˜ 효과λ₯Ό μ΅œλŒ€ν•œ μ–΅μ œν•˜μ—¬ 였λ₯˜λ₯Ό ν”Όν•œλ‹€.
  2. ν”„λ‘œκ·Έλž¨μ˜ μ•ˆμ •μ„±μ„ 높인닀.

이런 ν”„λ‘œκ·Έλž˜λ° νŒ¨λŸ¬λ‹€μž„μ„ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ΄λΌκ³  ν•©λ‹ˆλ‹€.


λ°˜ν™˜λ¬Έ

return ν‚€μ›Œλ“œμ™€ ν‘œν˜„μ‹μœΌλ‘œ λ°˜ν™˜λ¬Έμ„ λ§Œλ“€κ³  ν•¨μˆ˜ μ™ΈλΆ€λ‘œ λ°˜ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μžμ„Έν•˜κ²Œ μ„€λͺ…ν•  ν•„μš”λŠ” μ—†μ§€λ§Œ, 짚고 λ„˜μ–΄κ°€μ•Ό ν•˜λŠ” 뢀뢄이 μžˆμŠ΅λ‹ˆλ‹€.

ν•¨μˆ˜ ν˜ΈμΆœμ€ ν‘œν˜„μ‹μ΄λΌλŠ” 것을 κΈ°μ–΅ν•˜μ‹œλ‚˜μš”? ν•¨μˆ˜ 호좜 ν‘œν˜„μ‹μ€ return ν‚€μ›Œλ“œκ°€ λ°˜ν™˜ν•œ λ°˜ν™˜ κ°’μœΌλ‘œ ν‰κ°€λ©λ‹ˆλ‹€.

λ°˜ν™˜λ¬Έ(return λ¬Έ)은 μ•„λž˜μ™€ 같은 역할을 ν•©λ‹ˆλ‹€.

  1. ν•¨μˆ˜μ˜ 싀행을 μ€‘λ‹¨ν•˜κ³  μ™ΈλΆ€λ‘œ 결과값을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
    function sum(a, b){
      return a + b;
    
      console.log(a, b);    // μ‹€ν–‰λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
    }
    
    sum(1, 2);              // 3인 ν•¨μˆ˜ 호좜 ν‘œν˜„μ‹μž…λ‹ˆλ‹€.
  2. λ°˜ν™˜λ¬Έμ„ μ§€μ •ν•˜μ§€ μ•Šκ±°λ‚˜ μƒλž΅ν•˜λ©΄ undefinedλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
    function foo(){
      return;
    }
    
    function bar(){
    }
    
    console.log(foo());     // undefined
    console.log(bar());     // undefined
  3. return ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•  λ•Œ μ€„λ°”κΏˆ(κ°œν–‰λ¬Έμžμ˜ μ‚¬μš©)을 ν•œλ‹€λ©΄ ASI(μ„Έλ―Έμ½œλ‘  μžλ™ μ‚½μž… κΈ°λŠ₯)에 μ˜ν•΄ undefinedκ°€ λ°˜ν™˜λ©λ‹ˆλ‹€.
    function sum(a, b){
      return
        a + b;
    }
    /*
      // μ‹€μ œ 평가
      function sum(a, b){
        return;
          a + b;
      }
     */
    
    console.log(sum(1, 2)); // undefined
  4. λ°˜ν™˜λ¬Έμ€ ν•¨μˆ˜μ˜ λͺΈμ²΄μ—μ„œλ§Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ‚˜λ¨Έμ§€λŠ” SyntaxError: Illegal return statement μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€.
    • Node.jsλŠ” λͺ¨λ“ˆ μ‹œμŠ€ν…œμœΌλ‘œ 파일 μŠ€μ½”ν”„λ₯Ό κ°€μ§‘λ‹ˆλ‹€. 즉, return을 μ „μ—­μ—μ„œ μ‚¬μš©ν•΄λ„ μ—λŸ¬κ°€ λ‚˜μ§€λŠ” μ•Šμ•„μš”.

ν•¨μˆ˜μ˜ μ’…λ₯˜

ν•¨μˆ˜λŠ” μ—¬λŸ¬ ν˜•νƒœκ°€ μ‘΄μž¬ν•©λ‹ˆλ‹€.

ν•¨μˆ˜ μ •μ˜ 방식, 순수/λΉ„μˆœμˆ˜ ν•¨μˆ˜λ„ λ°°μ› μŠ΅λ‹ˆλ‹€. 그런데 또 무슨 μ’…λ₯˜κ°€ μžˆλŠ” κ±ΈκΉŒμš”?

μ΄λŠ” ν•¨μˆ˜μ˜ μ‚¬μš©μ²˜μ— μžˆμŠ΅λ‹ˆλ‹€. ν•˜λ‚˜μ”© μ‚΄νŽ΄λ³ΌκΉŒμš”?

  • μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜(Immediately Invoked Function Expression, IIFE)

    • ν•¨μˆ˜ μ„ μ–Έκ³Ό λ™μ‹œμ— μ¦‰μ‹œ ν˜ΈμΆœλ˜λŠ” ν•¨μˆ˜λ‘œ, λ‹€μ‹œ ν˜ΈμΆœν•  수 μ—†μŠ΅λ‹ˆλ‹€.
    • κΈ°λͺ… ν•¨μˆ˜λ‘œ μž‘μ„±ν•΄λ„ 상관 μ—†μœΌλ‚˜, λ‹€μ‹œ μ‚¬μš©ν•  수 μ—†μœΌλ―€λ‘œ 읡λͺ… ν•¨μˆ˜λ‘œ μž‘μ„±ν•˜λŠ” 것이 μΌλ°˜μ μž…λ‹ˆλ‹€.
    • λ°˜λ“œμ‹œ κ·Έλ£Ή μ—°μ‚°μž(())둜 감싸야 ν•©λ‹ˆλ‹€. κ·Έ μ΄μœ λŠ” ν•¨μˆ˜ μ„ μ–Έλ¬Έμ˜ ν˜•μ‹κ³Ό μΌμΉ˜ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ©°, ASI κΈ°λŠ₯ λ˜ν•œ μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
      // SyntaxError: Function statements require a function name
      function (){
        // κΈ°λŠ₯ μ •μ˜
      }();
      
      // SyntaxError: Unexpected token ')'
      function sum(){
        // κΈ°λŠ₯ μ •μ˜
      }();
    • μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜λŠ” μ΄λ ‡κ²Œ μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
      // 1
      (function() {
        // κΈ°λŠ₯ μ •μ˜
      }());
      
      // 2
      (function(){
        // κΈ°λŠ₯ μ •μ˜
      })();
      
      // 3
      !function(){
        // κΈ°λŠ₯ μ •μ˜
      }();
      
      // 4
      +function(){
        // κΈ°λŠ₯ μ •μ˜
      }();
    • 일반 ν•¨μˆ˜μ²˜λŸΌ 값을 λ°˜ν™˜ν•  수 있고, 인수λ₯Ό 전달할 수 μžˆμŠ΅λ‹ˆλ‹€.
      // κ°’ λ°˜ν™˜
      const sum = (function(){
        return 10 + 100;
      }());
      
      console.log(sum); // 110
      
      const sub = (function(a, b){
        return a - b;
      }(10, 100));
      
      console.log(sub); // -90
    • 정리 : μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜λŠ” μ‘΄μž¬ν•  수 μžˆλŠ” λ³€μˆ˜μ™€ ν•¨μˆ˜μ˜ μΆ©λŒμ„ λ°©μ§€ν•˜λŠ” 곳에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
  • μž¬κ·€ ν•¨μˆ˜(Recursive Function) : ν•¨μˆ˜κ°€ 자기 μžμ‹ μ„ ν˜ΈμΆœν•˜λŠ” 것은 μž¬κ·€ 호좜(Recursive Call)이라고 ν•©λ‹ˆλ‹€.

    • μž¬κ·€ ν•¨μˆ˜λŠ” μžμ‹ μ„ λ¬΄ν•œμœΌλ‘œ ν˜ΈμΆœν•˜λ―€λ‘œ λ°˜λ“œμ‹œ νƒˆμΆœ 쑰건을 λͺ…μ‹œν•΄μ•Ό ν•©λ‹ˆλ‹€.
      function factorial(num){
        if(num === 1) return 1;           // νƒˆμΆœ 쑰건
        return num * factorial(num - 1);  // μž¬κ·€ 호좜
      }
      
      const a = 5;
      
      factorial(a);                       // μž¬κ·€ ν•¨μˆ˜ 호좜
  • λ‚΄λΆ€ ν•¨μˆ˜(Inner Function) : 쀑첩 ν•¨μˆ˜(Nested Funtion)라고도 ν•©λ‹ˆλ‹€. 쀑첩 ν•¨μˆ˜λ₯Ό ν¬ν•¨ν•˜λŠ” ν•¨μˆ˜λŠ” μ™ΈλΆ€ ν•¨μˆ˜(Outer Function)라고 ν•©λ‹ˆλ‹€.

    • λ‚΄λΆ€ ν•¨μˆ˜λŠ” μ™ΈλΆ€ ν•¨μˆ˜μ˜ 헬퍼 ν•¨μˆ˜(Helper Function)의 역할을 ν•©λ‹ˆλ‹€.
    • ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•  수 μžˆμœΌλ―€λ‘œ μ œμ–΄λ¬Έ λ“±μ˜ μ½”λ“œ λΈ”λ‘μ—μ„œ ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜μ§€λŠ” λ§ˆμ„Έμš”!
    • λ‚΄λΆ€ ν•¨μˆ˜λŠ” μŠ€μ½”ν”„μ™€ ν΄λ‘œμ €μ— 관련이 μžˆμœΌλ―€λ‘œ, μ°¨ν›„ μžμ„Ένžˆ λ‹€λ£Ήλ‹ˆλ‹€.
      // μ™ΈλΆ€ ν•¨μˆ˜
      function outer(){
        const a = 1;
      
        // λ‚΄λΆ€ ν•¨μˆ˜
        function inner(){
          const b = 2;
          // μ™ΈλΆ€ ν•¨μˆ˜μ˜ λ³€μˆ˜ μ°Έμ‘° κ°€λŠ₯
          console.log(a + b);
        }
      
        inner();
      }
      
      outer();  // 3
      inner();  // ReferenceError: inner is not defined
  • 콜백 ν•¨μˆ˜(Callback Function) : ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜λ‘œ 내뢀에 μ „λ‹¬λ˜λŠ” ν•¨μˆ˜λ₯Ό 콜백 ν•¨μˆ˜λΌκ³  ν•˜λ©°, 이λ₯Ό 전달받은 ν•¨μˆ˜λ₯Ό κ³ μ°¨ ν•¨μˆ˜(Higher-Order Function)이라고 ν•©λ‹ˆλ‹€.

    // κ³ μ°¨ ν•¨μˆ˜ logPrint()
    function logPrint(n, f){
      for(let i = 0; i < n; i++){
        f(i); // 콜백 ν•¨μˆ˜ f() 호좜
      }
    }
    • ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° νŒ¨λŸ¬λ‹€μž„μ—μ„œ 맀우 μ€‘μš”ν•œ μš”μ†Œμ΄λ©°, μΆ”ν›„ 더 μžμ„Ένžˆ λ‹€λ£Ήλ‹ˆλ‹€.
    • λ‚΄λΆ€ ν•¨μˆ˜κ°€ μ™ΈλΆ€ ν•¨μˆ˜λ₯Ό λ•λŠ” 것과 같이 콜백 ν•¨μˆ˜λ„ κ³ μ°¨ ν•¨μˆ˜μ— μ „λ‹¬λ˜μ–΄ λ•λŠ” 역할을 ν•œλ‹€. 콜백 ν•¨μˆ˜λŠ” ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ μ£Όμž…λ˜λ―€λ‘œ λ‚΄λΆ€ ν•¨μˆ˜μ™€ 달리 자유둭게 ꡐ체할 수 μžˆμŠ΅λ‹ˆλ‹€. 즉, κ³ μ°¨ ν•¨μˆ˜λŠ” 콜백 ν•¨μˆ˜λ₯Ό μžμ‹ μ˜ μΌλΆ€λΆ„μΈλ§ˆλƒ₯ ν•©μ„±ν•©λ‹ˆλ‹€.
    • κ³ μ°¨ ν•¨μˆ˜λŠ” λ§€κ°œλ³€μˆ˜λ₯Ό 톡해 전달받은 콜백 ν•¨μˆ˜μ˜ 호좜 μ‹œμ μ„ κ²°μ •ν•΄μ„œ ν˜ΈμΆœν•˜λŠ”λ°, 이 λ•Œ 콜백 ν•¨μˆ˜μ— 인수λ₯Ό 전달할 수 μžˆμŠ΅λ‹ˆλ‹€.
    • κ³ μ°¨ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œλ§Œ ν˜ΈμΆœλ˜λŠ” 경우, 콜백 ν•¨μˆ˜λ₯Ό 읡λͺ… ν•¨μˆ˜ λ¦¬ν„°λŸ΄λ‘œ μ •μ˜ν•˜λŠ” 것이 μΌλ°˜μ μž…λ‹ˆλ‹€.
      logPrint(5, function(i){
        console.log(`INFO::: 콜백 ν•¨μˆ˜ μ‹€ν–‰ ${i}`);
      });
    • λ‹€λ₯Έ κ³³μ—μ„œ 콜백 ν•¨μˆ˜λ₯Ό 호좜될 경우 ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ 콜백 ν•¨μˆ˜λ₯Ό μ •μ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.
      const parse = function(i){
        if(i % 2) console.log(i);
      };
      
      logPrint(5, parse);
    • 비동기 ν”„λ‘œκ·Έλž˜λ°, λ°°μ—΄ κ³ μ°¨ ν•¨μˆ˜μ—λ„ μ“°μ΄λŠ” 콜백 ν•¨μˆ˜λŠ” 맀우 μ€‘μš”ν•œ ν•­λͺ©μ΄λ―€λ‘œ λ°˜λ“œμ‹œ μ΄ν•΄ν•˜κ³  λ„˜μ–΄κ°‘μ‹œλ‹€!
      // 콜백 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œ 이벀트 처리
      document.getElementById('printBtn').addEventListner('click', function(){
        console.log('λ²„νŠΌμ΄ ν΄λ¦­λ˜μ—ˆμŠ΅λ‹ˆλ‹€.');
      });
      
      // 콜백 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œ 비동기 처리
      setTimeout(function(){
        console.log('1초 κ²½κ³Όν–ˆμŠ΅λ‹ˆλ‹€.');
      }, 1000);
      
      // 콜백 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œ λ°°μ—΄ κ³ μ°¨ ν•¨μˆ˜
      // map, filter, reduce λ“± λ‹€μ–‘ν•œ κ³ μ°¨ ν•¨μˆ˜λŠ” μ°¨ν›„ μžμ„Ένžˆ μ•Œμ•„λ΄…λ‹ˆλ‹€!
      const result1 = [1, 2, 3].map(function(item){
        return item * 2;
      });
      
      console.log(result1); // [2, 4, 5]