πŸ“† 2025.04.24 ‐ Advanced JavaScript: Functions, Prototypes, Closures, and Classes

rogieΒ·2025λ…„ 4μ›” 24일

likelion-posting

λͺ©λ‘ 보기
8/10

🧠 배운 점 & 정리

였늘 κ³΅λΆ€ν•˜λ©΄μ„œ μΈμ‚¬μ΄νŠΈ, κ°œλ… μš”μ•½ λ“±

  • ν”„λ‘œν† νƒ€μž… 체인을 μ΄μš©ν•œ 상속 κΈ°λŠ₯

    • ν•˜μœ„ μƒμ„±μžμ˜ ν”„λ‘œν† νƒ€μž…μ„ μƒμœ„ μƒμ„±μžμ˜ 객체둜 μ§€μ •

    • μƒμœ„ μƒμ„±μžμ˜ λͺ¨λ“  속성을 λ¬Όλ €λ°›μ•„ μ‚¬μš©ν•  수 있음

    • 상속 ex03-04.js

      • 쀑볡속성

        /**
         * 고등학ꡐ 성적관리 μƒμ„±μž ν•¨μˆ˜(총점과 평균 계산)
        * @param {number} kor κ΅­μ–΄ 점수
        * @param {number} eng μ˜μ–΄ 점수
        */
        function HighSchool(kor, eng) {
          // 속성 초기 ν™”
          this.kor = kor;
          this.eng = eng;
        }
        
        HighSchool.prototype.sum = function () {
          return this.kor + this.eng;
        };
        
        HighSchool.prototype.avg = function () {
          return this.sum() / 2;
        };
        
        const s1 = new HighSchool(100, 91);
        console.log("고등학ꡐ 총점", s1.sum());
        console.log("고등학ꡐ 평균", s1.avg());
        

        image

        /**
         * λŒ€ν•™κ΅ 성적관리 μƒμ„±μž ν•¨μˆ˜(총점, 평균과 학점 계산)
        * @param {number} kor κ΅­μ–΄ 점수
        * @param {number} eng μ˜μ–΄ 점수
        */
        function College(kor, eng) {
          this.kor = kor;
          this.eng = eng;
        }
        
        College.prototype.sum = function () {
          return this.kor + this.eng;
        };
        
        College.prototype.avg = function () {
          return this.sum() / 2;
        };
        College.prototype.grade = function () {
          const avg = this.avg();
          if (avg >= 90) {
            return "A";
          } else if (avg >= 80) {
            return "B";
          } else if (avg >= 70) {
            return "C";
          } else if (avg >= 60) {
            return "D";
          } else {
            return "F";
          }
        };
        
        const c1 = new College(80, 91);
        console.log("λŒ€ν•™κ΅ 총점", c1.sum());
        console.log("λŒ€ν•™κ΅ 평균", c1.avg());
        console.log("λŒ€ν•™κ΅ 학점", c1.grade());

        image

      • 상속 λ°›λŠ” μ½”λ“œ
        image

        /**
         * 고등학ꡐ 성적관리 μƒμ„±μž ν•¨μˆ˜(총점과 평균 계산)
        * @param {number} kor κ΅­μ–΄ 점수
        * @param {number} eng μ˜μ–΄ 점수
        */
        function HighSchool(kor, eng) {
          // 속성 초기 ν™”
          this.kor = kor;
          this.eng = eng;
        }
        
        HighSchool.prototype.sum = function () {
          return this.kor + this.eng;
        };
        
        HighSchool.prototype.avg = function () {
          // μ†Œμˆ˜ μ²«μ§Έμžλ¦¬μ—μ„œ λ°˜μ˜¬λ¦Όν•œλ‹€
          return Math.round(this.sum() / 2);
        };
        
        const s1 = new HighSchool(100, 91);
        console.log("고등학ꡐ 총점", s1.sum());
        console.log("고등학ꡐ 평균", s1.avg());

        image

        /**
         * λŒ€ν•™κ΅ 성적관리 μƒμ„±μž ν•¨μˆ˜(총점, 평균과 학점 계산)
        * @param {number} kor κ΅­μ–΄ 점수
        * @param {number} eng μ˜μ–΄ 점수
        */
        function College(kor, eng) {
          this.kor = kor;
          this.eng = eng;
        }
        
        // Collegeκ°€ HighSchool을 상속 λ°›λŠ”λ‹€
        College.prototype = new HighSchool();
        College.prototype.**constructor** = College;
        
        College.prototype.grade = function () {
          const avg = this.avg();
          if (avg >= 90) {
            return "A";
          } else if (avg >= 80) {
            return "B";
          } else if (avg >= 70) {
            return "C";
          } else if (avg >= 60) {
            return "D";
          } else {
            return "F";
          }
        };
        
        const c1 = new College(80, 91);
        console.log("λŒ€ν•™κ΅ 총점", c1.sum());
        console.log("λŒ€ν•™κ΅ 평균", c1.avg());
        console.log("λŒ€ν•™κ΅ 학점", c1.grade());

        constructorΒ λ©”μ„œλ“œλŠ”Β ν΄λž˜μŠ€μ˜ μΈμŠ€ν„΄μŠ€ 객체λ₯Ό μƒμ„±ν•˜κ³  μ΄ˆκΈ°ν™”ν•˜λŠ” νŠΉλ³„ν•œ λ©”μ„œλ“œμž…λ‹ˆλ‹€.

        • gpt μ„€λͺ…

          • HighSchool: 점수 β†’ sum(), avg() κ³„μ‚°λ§Œ λ‹΄λ‹Ή
          • College: HighSchool κΈ°λŠ₯ + grade() ν™•μž₯
          • College.prototype = new HighSchool() λ₯Ό 톡해 상속 κ΅¬ν˜„
          • constructorλŠ” λ‹€μ‹œ College둜 λ˜λŒλ €μ€˜μ•Ό 정확함
        • constructorλž€?

          • πŸ”§ constructorλž€?

            • constructorλŠ” 객체의 ν”„λ‘œν† νƒ€μž…(prototype) 객체에 기본으둜 ν¬ν•¨λœ 속성이야.
            • 이 속성은 ν•΄λ‹Ή 객체가 μ–΄λ–€ μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λ˜μ—ˆλŠ”μ§€λ₯Ό κ°€λ¦¬μΌœ.
            • λͺ¨λ“  ν•¨μˆ˜λŠ” 기본적으둜 .prototype.constructor 속성을 κ°€μ§€κ³  μžˆμ–΄.

            μ˜ˆμ‹œ:

            function HighSchool(kor, eng) {
              this.kor = kor;
              this.eng = eng;
            }
            
            console.log(HighSchool.prototype.constructor === HighSchool); // βœ… true
            

            이 말은 즉,

            const s1 = new HighSchool(100, 90);

            λ₯Ό ν–ˆμ„ λ•Œ, s1.constructor === HighSchool 이 성립해.

            μ™œλƒλ©΄ s1.__proto__ === HighSchool.prototype 이고, κ·Έ μ•ˆμ— μžˆλŠ” .constructorκ°€ HighSchool을 κ°€λ¦¬ν‚€λ‹ˆκΉŒ!


          • πŸ” 근데 상속할 λ•Œ λ¬Έμ œκ°€ 생겨!

            College.prototype = new HighSchool();

            μ΄λ ‡κ²Œ μƒμ†ν•˜λ©΄ College.prototype은 이제 HighSchool의 μΈμŠ€ν„΄μŠ€κ°€ λ˜λ‹ˆκΉŒ,

            College.prototype.constructorλŠ” HighSchool을 κ°€λ¦¬ν‚€κ²Œ 돼.

            console.log(College.prototype.constructor === HighSchool); // ❌ μš°λ¦¬κ°€ μ›ν•˜λŠ” 게 μ•„λ‹˜

            κ·Έλž˜μ„œ μ›λž˜μ˜ μƒμ„±μž 정보가 꼬이게 되고, 이걸 λͺ…μ‹œμ μœΌλ‘œ λ‹€μ‹œ μ„€μ •ν•΄μ€˜μ•Ό ν•΄:

            College.prototype.constructor = College;

            μ΄λ ‡κ²Œ ν•˜λ©΄:

            const c1 = new College(80, 91);
            console.log(c1.constructor === College); // βœ… true

          • πŸ” μ™œ constructorλ₯Ό λ°”λ₯΄κ²Œ μ§€μ •ν•΄μ•Ό ν• κΉŒ?

            1. 디버깅/λ‘œκΉ…ν•  λ•Œ μ–΄λ–€ μƒμ„±μžλ‘œ λ§Œλ“€μ–΄μ‘ŒλŠ”μ§€ μ•Œ 수 있음
            2. 클래슀 체계λ₯Ό 흉내 λ‚Ό λ•Œ μ •ν™•ν•œ 정보 제곡
            3. μ–΄λ–€ ν”„λ ˆμž„μ›Œν¬/λΌμ΄λΈŒλŸ¬λ¦¬λŠ” constructor 값을 보고 νƒ€μž… λΆ„κΈ° μ²˜λ¦¬ν•˜κΈ°λ„ 함

          • πŸ“Œ μš”μ•½

            • .constructorλŠ” μ–΄λ–€ μƒμ„±μž ν•¨μˆ˜λ‘œ λ§Œλ“€μ–΄μ‘ŒλŠ”μ§€ μ•Œλ €μ£ΌλŠ” 속성
            • 상속할 λ•Œ prototype = new Parent() ν•˜λ©΄ .constructorκ°€ κΌ¬μ΄λ―€λ‘œ constructorλ₯Ό 직접 μž¬μ§€μ •ν•΄μ€˜μ•Ό 함
            • λ°”λ₯΄κ²Œ 지정해두면 λ””λ²„κΉ…μ΄λ‚˜ νƒ€μž… ν™•μΈμ—μ„œ μœ λ¦¬ν•¨
    • 상속 ex03-04.jsλ₯Ό ex03-05.js둜
      HighSchool β†’ College 상속 흐름 μ‹œκ° 정리

      /* ex03-04 */
      /**
       * 고등학ꡐ 성적관리 μƒμ„±μž ν•¨μˆ˜(총점과 평균 계산)
        * @param {number} kor κ΅­μ–΄ 점수
        * @param {number} eng μ˜μ–΄ 점수
        */
      function HighSchool(kor, eng) {
        // 속성 초기 ν™”
        this.kor = kor;
        this.eng = eng;
      }
      
      HighSchool.prototype.sum = function () {
        return this.kor + this.eng;
      };
      
      HighSchool.prototype.avg = function () {
        // μ†Œμˆ˜ μ²«μ§Έμžλ¦¬μ—μ„œ λ°˜μ˜¬λ¦Όν•œλ‹€
        return Math.round(this.sum() / 2);
      };
      
      const s1 = new HighSchool(100, 91);
      console.log("고등학ꡐ 총점", s1.sum());
      console.log("고등학ꡐ 평균", s1.avg());
      
      {...}
      console.log(College.prototype);
      // College의 ν”„λ‘œν† νƒ€μž… 좜λ ₯
      

      image

      /* ex03-05 */
      {...}
      /**
       * λŒ€ν•™κ΅ 성적관리 μƒμ„±μž ν•¨μˆ˜(총점, 평균과 학점 계산)
        * @param {number} kor κ΅­μ–΄ 점수
        * @param {number} eng μ˜μ–΄ 점수
        */
      function College(kor, eng) {
        this.kor = kor;
        this.eng = eng;
      }
      
      // Collegeκ°€ HighSchool을 상속 λ°›λŠ”λ‹€
      
      function inherite(Parent, Child) {
        // 첫번째 방법
        const F = new Function();
        F.prototype = HighSchool.prototype; // F의 ν”„λ‘œν† νƒ€μž…μ„ HighSchool의 ν”„λ‘œν† νƒ€μž…μœΌλ‘œ λ³€κ²½
        College.prototype = new F(); // FμΈμŠ€ν„΄μŠ€ 생성후 College의 ν”„λ‘œν† νƒ€μž…μœΌλ‘œ λŒ€μž…ν•œλ‹€
        College.prototype.constructor = College;
        
        // 2번째 방법
        Child.prototype = Object.create(Parent.prototype);
        //createν•¨μˆ˜λŠ” μ§€μ •ν•œ prototype 객체λ₯Ό μ°Έμ‘°ν•˜λŠ” μΈμŠ€ν„΄μŠ€ 생성
        Child.prototype.constructor = Child; 
        // μžμ‹ μƒμ„±μžμ˜ constructor ν”„λ‘œνΌν‹° 볡원
      }
      
      inherite(HighSchool, College);
      
      College.prototype.grade = function () {
        const avg = this.avg();
        if (avg >= 90) {
          return "A";
        } else if (avg >= 80) {
          return "B";
        } else if (avg >= 70) {
          return "C";
        } else if (avg >= 60) {
          return "D";
        } else {
          return "F";
        }
      };
      
      const c1 = new College(80, 91);
      console.log("λŒ€ν•™κ΅ 총점", c1.sum());
      console.log("λŒ€ν•™κ΅ 평균", c1.avg());
      console.log("λŒ€ν•™κ΅ 학점", c1.grade());
      
      console.log(College.prototype);
      // College의 ν”„λ‘œν† νƒ€μž… 좜λ ₯
      

      image


  • Class μ‚¬μš©

    • ECMAScript6(2015)에 μΆ”κ°€λœ ν‚€μ›Œλ“œ

    • 객체지ν–₯ μ–Έμ–΄μ˜ class와 λΉ„μŠ·ν•œ λ°©μ‹μœΌλ‘œ μƒμ„±μž ν•¨μˆ˜λ₯Ό 기술

    • 객체λ₯Ό μƒμ„±ν•˜κ³  prototype 기반의 상속을 보닀 λͺ…λ£Œν•˜κ²Œ ν‘œν˜„

    • classλŠ” 사싀 **ν•¨μˆ˜**이며 class μ„ μ–Έλ¬Έκ³Ό class ν‘œν˜„μ‹ λ°©μ‹μœΌλ‘œ μ‚¬μš©

    • class μ„ μ–Έλ¬Έ

      // κΈ°λ³Έ νƒ€μž…
      class 클래슀λͺ… {...}
      // μ˜ˆμ‹œ
      class hi {...}
      • class ν‘œν˜„μ‹
      // κΈ°λ³Έ νƒ€μž…
      const λ³€μˆ˜ = class {...}
      // μ˜ˆμ‹œ
      const hi = class {...}
    • Class body와 λ©”μ„œλ“œ μ •μ˜

      클래슀의 바디에 클래슀 λ©€λ²„λ³€μˆ˜(속성)와 λ©”μ„œλ“œ μ •μ˜

      λ©€λ²„λ³€μˆ˜μ˜ μ΄ˆκΈ°ν™”λŠ” Constructor λ©”μ„œλ“œμ— μ •μ˜

    • Constructor λ©”μ„œλ“œ(μƒμ„±μž)

      • 객체λ₯Ό μƒμ„±ν•˜κ³  μ΄ˆκΈ°ν™” ν•˜λŠ” λ©”μ„œλ“œ(μƒλž΅ κ°€λŠ₯)
      • 주둜 클래슀 λ©€λ²„λ³€μˆ˜λ₯Ό μ΄ˆκΈ°ν™”ν•˜λŠ” μž‘μ—…
      • constructorλΌλŠ” μ΄λ¦„μœΌλ‘œ μž‘μ„±
      • ν•˜λ‚˜λ§Œ μž‘μ„± κ°€λŠ₯
      • super()둜 λΆ€λͺ¨μ˜ μƒμ„±μž 호좜 κ°€λŠ₯
      // βœ… Class 문법 (ES6)
      class HighSchool {
        constructor(kor, eng) {
          this.kor = kor;
          this.eng = eng;
        }
      }
      
      const s1 = new HighSchool(100, 90);
      console.log(s1.kor, s1.eng);
      
      // βœ… Function μƒμ„±μž 방식
      function HighSchool(kor, eng) {
        this.kor = kor;
        this.eng = eng;
      }
      
      const s1 = new HighSchool(100, 90);
      console.log(s1.kor, s1.eng);
      

  • ν΄λ‘œμ €

    • ν΄λ‘œμ €λž€

      • 싀행이 λλ‚œ μ™ΈλΆ€ ν•¨μˆ˜μ˜ λ³€μˆ˜μ— μ ‘κ·Όν•  수 μžˆλŠ” λ‚΄λΆ€ ν•¨μˆ˜

      • ν•¨μˆ˜κ°€ μƒμ„±λ˜λŠ” μ‹œμ μ„ κΈ°μ€€μœΌλ‘œ μ ‘κ·Ό κ°€λŠ₯ν•œ λ³€μˆ˜λŠ”, κ·Έ μœ νš¨λ²”μœ„κ°€ 사라진 후에도 μ ‘κ·Ό κ°€λŠ₯

      • ν΄λ‘œμ €λ‘œ 인해 유효 λ²”μœ„κ°€ 사라진 λ³€μˆ˜μ™€ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 있고, λ³€μˆ˜μ˜ 경우 κ·Έ 값을 λ³€κ²½ν•  μˆ˜λ„ μžˆλ‹€.

      • ex04-01.js

        const topLevel = "μ΅œμƒμœ„ λ³€μˆ˜";
        
        function outer() {
          const innerVal = "outer의 μ§€μ—­λ³€μˆ˜";
          console.log(topLevel); //=> 1️⃣
          console.log(innerVal); //=> 2️⃣
        }
        
        outer();
        console.log(topLevel); //=> 3️⃣
        console.log(innerVal); //=> 4️⃣
        /* 좜λ ₯ μˆœμ„œ
          1️⃣ 2️⃣ 3️⃣ (4οΈβƒ£λŠ” μ—λŸ¬) 
        */
        • 1️⃣ μ „μ—­ λ³€μˆ˜ topLevel은 ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œλ„ μ ‘κ·Ό κ°€λŠ₯ν•˜λ‹€.
          μŠ€μ½”ν”„ 체인에 따라 ν•˜μœ„ μŠ€μ½”ν”„μ—μ„œ μƒμœ„ μŠ€μ½”ν”„ λ³€μˆ˜λ₯Ό μ°ΎλŠ”λ‹€.
        • 2️⃣ innerVal은 outer ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ„ μ–Έλœ μ§€μ—­ λ³€μˆ˜μ΄λ‹€.
          ν•¨μˆ˜ μ•ˆμ—μ„œλŠ” 자유둭게 μ°Έμ‘° κ°€λŠ₯ν•˜μ§€λ§Œ ν•¨μˆ˜ λ°–μ—μ„œλŠ” λΆˆκ°€ν•˜λ‹€.
        • 3️⃣ topLevel은 μ „μ—­ λ³€μˆ˜μ΄λ―€λ‘œ ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œλ„ 문제 없이 접근됨.
          μ „μ—­ μŠ€μ½”ν”„μ—μ„œ μ„ μ–Έλœ λ³€μˆ˜λŠ” μ–΄λ””μ„œλ“  μ°Έμ‘°κ°€ κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.
        • 4️⃣ innerVal은 outer ν•¨μˆ˜κ°€ μ’…λ£Œλ˜λ©΄ μ‚¬λΌμ§€λŠ” μ§€μ—­ λ³€μˆ˜μ΄λ‹€.
          ν•¨μˆ˜ λ°–μ—μ„œ μ ‘κ·Όν•˜λ©΄ ReferenceErrorκ°€ λ°œμƒν•˜κ²Œ λœλ‹€.

        const topLevel = "μ΅œμƒμœ„ λ³€μˆ˜";
        
        function outer() {
          const innerVal = "outer의 μ§€μ—­λ³€μˆ˜";
          console.log(topLevel); // 1️⃣
          console.log(innerVal); // 2️⃣
          return innerVal;
        }
        
        outer();
        console.log(topLevel); // 3️⃣
        console.log(innerVal); // 4️⃣
        
        /* 좜λ ₯μˆœμ„œ
          1️⃣ 2️⃣ 3️⃣ (4οΈβƒ£λŠ” μ—λŸ¬)
        */
        • 1️⃣ topLevel은 ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ μ„ μ–Έλœ μ „μ—­ λ³€μˆ˜μ΄λ©°, ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μžλ™μœΌλ‘œ μ°Έμ‘°λœλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μŠ€μ½”ν”„ 체인 덕뢄에 ν•˜μœ„ μŠ€μ½”ν”„ μ—μ„œλŠ” μƒμœ„ μŠ€μ½”ν”„μ— μžˆλŠ” λ³€μˆ˜μ— μ ‘κ·Όν•  수 있게 λœλ‹€.
        • 2️⃣ innerVal은 outer ν•¨μˆ˜ μ•ˆμ—μ„œ μ„ μ–Έλœ μ§€μ—­ λ³€μˆ˜μ΄κΈ° λ•Œλ¬Έμ— ν•΄λ‹Ή ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œλ§Œ μœ νš¨ν•˜λ‹€. μ§€μ—­ μŠ€μ½”ν”„λŠ” ν•¨μˆ˜ μ‹€ν–‰ μ‹œ 생기며 ν•¨μˆ˜ μ’…λ£Œμ™€ ν•¨κ»˜ λ©”λͺ¨λ¦¬μ—μ„œ μ œκ±°λœλ‹€.
        • 3️⃣ topLevel은 전역에 μ„ μ–Έλ˜μ–΄ 있기 λ•Œλ¬Έμ— μ–΄λ””μ„œλ“  μ ‘κ·Ό κ°€λŠ₯ν•˜λ‹€.
          ν•¨μˆ˜ λ°–μ˜ console.log(topLevel)도 μ „ν˜€ 문제 없이 μ‹€ν–‰λœλ‹€.
          μ „μ—­ λ³€μˆ˜λŠ” 전체 μ½”λ“œμ—μ„œ 곡유 κ°€λŠ₯ν•œ 값이닀.
        • 4️⃣ innerVal은 outer λ‚΄λΆ€μ—μ„œ μ„ μ–Έλ˜μ—ˆκΈ° λ•Œλ¬Έμ— μ™ΈλΆ€μ—μ„œλŠ” μ°Έμ‘°ν•  수 μ—†λ‹€. ν•¨μˆ˜ λ°–μ—μ„œ μ ‘κ·Όν•˜λ €κ³  ν•˜λ©΄ ReferenceError λ°œμƒ.

          μ΄λŠ” ν•¨μˆ˜ μŠ€μ½”ν”„μ— λ”°λ₯Έ 정상적인 λ™μž‘μ΄λ‹€.

        const topLevel = "μ΅œμƒμœ„ λ³€μˆ˜";
        
        function outer() {
          const innerVal = "outer의 μ§€μ—­λ³€μˆ˜";
          console.log(topLevel); // => 1️⃣
          console.log(innerVal); // => 2️⃣
          const innerFn = function () {
            console.log(innerVal); // => 3️⃣
          };
          innerFn();
        }
        
        outer();
        console.log(topLevel); // => 4️⃣
        console.log(innerVal); // => 5️⃣
        /* 좜λ ₯ μˆœμ„œ
        1️⃣ 2️⃣ 3️⃣ 4️⃣ (5οΈβƒ£λŠ” μ—λŸ¬)
        */
        • 1️⃣ μ „μ—­ λ³€μˆ˜λŠ” ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œλ„ μ°Έμ‘°ν•  수 μžˆλŠ” μŠ€μ½”ν”„ 체인을 κ°€μ§„λ‹€.
        • 2️⃣ μ§€μ—­ λ³€μˆ˜λŠ” μ„ μ–Έλœ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œλ§Œ μœ νš¨ν•˜λ©° μ™ΈλΆ€μ—μ„œλŠ” λΆˆκ°€ν•˜λ‹€.
        • 3️⃣ 쀑첩 ν•¨μˆ˜λŠ” μƒμœ„ ν•¨μˆ˜μ˜ μ§€μ—­ λ³€μˆ˜κΉŒμ§€ μ ‘κ·Όν•  수 μžˆλŠ” ν΄λ‘œμ €λ‹€.
        • 4️⃣ μ „μ—­ λ³€μˆ˜λŠ” μ–΄λ””μ—μ„œλ“  μ ‘κ·Ό κ°€λŠ₯ν•˜μ—¬ 였λ₯˜ 없이 좜λ ₯λœλ‹€.
        • 5️⃣ innerVal 은 outerν•¨μˆ˜κ°€ μ’…λ£Œλ˜λ©΄ λ©”λͺ¨λ¦¬μ—μ„œ μ œκ±°λ˜λ―€λ‘œ 였λ₯˜.

        const topLevel = "μ΅œμƒμœ„ λ³€μˆ˜";
        
        function outer() {
          const innerVal = "outer의 μ§€μ—­λ³€μˆ˜";
          console.log(topLevel); // => 1️⃣
          console.log(innerVal); // => 2️⃣
          const innerFn = function () {
            console.log(innerVal); // => 3️⃣
          };
          return innerFn;
        }
        
        const innerFn = outer();
        console.log(topLevel); // => 4️⃣
        // console.log(innerVal); // => 5️⃣
        innerFn(); // => 6️⃣
        /* 좜λ ₯ μˆœμ„œ
        1️⃣ 2️⃣ 4️⃣ 6️⃣ (5οΈβƒ£λŠ” 주석 처리)
        */
        • 1️⃣ μ „μ—­ λ³€μˆ˜λŠ” ν•˜μœ„ ν•¨μˆ˜μ—μ„œλ„ μ ‘κ·Ό κ°€λŠ₯ν•˜λ‹€. μŠ€μ½”ν”„ 체인 덕뢄이닀.
        • 2️⃣ μ§€μ—­ λ³€μˆ˜λŠ” μ„ μ–Έλœ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œλ§Œ μ ‘κ·Ό κ°€λŠ₯ν•˜λ‹€. 정상 좜λ ₯λœλ‹€.
        • 3️⃣ λ‚΄λΆ€ ν•¨μˆ˜λŠ” λΆ€λͺ¨ ν•¨μˆ˜μ˜ μ§€μ—­ λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•  수 μžˆλ‹€. (ν΄λ‘œμ €)
        • 4️⃣ μ „μ—­ λ³€μˆ˜λŠ” μ–΄λ””μ—μ„œλ“  μ ‘κ·Ό κ°€λŠ₯ν•˜μ—¬ 였λ₯˜ 없이 좜λ ₯λœλ‹€.
        • 5️⃣ innerVal 은 외뢀에선 μ ‘κ·Όν•  수 μ—†μ–΄ 주석 ν•΄μ œ μ‹œ 였λ₯˜ λ°œμƒν•œλ‹€.
        • 6️⃣ innerFn은 outer의 μ§€μ—­λ³€μˆ˜λ₯Ό κΈ°μ–΅ν•˜λŠ” ν΄λ‘œμ €λ‘œ λ™μž‘ν•œλ‹€.

    • 컀링(currying)
      • μ—¬λŸ¬κ°œμ˜ 인자λ₯Ό λ°›λŠ” ν•¨μˆ˜λ₯Ό 단일 인자λ₯Ό λ°›λŠ” ν•¨μˆ˜μ˜ 체인으둜 ν˜ΈμΆœν•˜λ„λ‘ λ°”κΎΈλŠ” ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° 기법 쀑 ν•˜λ‚˜

        • sum(x, y) -> sum(x)(y)
      • ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° 언어에 λ§Žμ€ κ³΅ν—Œμ„ ν•œ 미ꡭ의 μˆ˜ν•™μž, λ…Όλ¦¬ν•™μžμΈ ν•˜μŠ€μΌˆ 컀리의 μ΄λ¦„μ—μ„œ λ”°μ˜΄

      • ν•¨μˆ˜μ˜ 가독성, μž¬μ‚¬μš©μ΄ 쒋아짐.

      • λ§ˆμ§€λ§‰ μΈμžκ°€ μž…λ ₯될 λ•ŒκΉŒμ§€ ν•¨μˆ˜μ˜ μ‹€ν–‰ 타이밍을 μ‘°μ ˆν•  수 있음.

      • ex04-03.js

        function sum(a, b, c) {
          return a + b + c;
        }
        console.log(sum(10, 20, 30));
        
        // ν•¨μˆ˜ 선언식
        let currySum = function (a) {
          return function (b) {
            return function (c) {
              return a + b + c;
            };
          };
        };
        
        // ν™”μ‚΄ν‘œ ν•¨μˆ˜
        currySum = (a) => (b) => (c) => a + b + c; 
        // μ‹€ν–‰ ν•  μ½”λ“œκ°€ a, b, c 각각 ν•˜λ‚˜μ΄κΈ° λ•Œλ¬Έμ—
        // μ€‘κ΄„ν˜Έ μƒλž΅ κ°€λŠ₯함
        
        console.log(currySum(10)(20)(30));

        πŸ“Œ μ •λ¦¬λœ 호좜 ꡬ쑰

        currySum(10)
           └──> returns (b) => (c) => a + b + c
        
        currySum(10)(20)
           └──> returns (c) => a + b + c
        
        currySum(10)(20)(30)
           └──> returns 60
      • ex04-04.js, index.html

          <script src="https://unpkg.com/lodash@4.17.21/lodash.js"></script>

        lodash 라이브러리의 μœ ν‹Έ ν•¨μˆ˜λ“€μ„ μ›Ήμ—μ„œ λ°”λ‘œ μ‚¬μš©ν•˜κΈ° μœ„ν•΄ μΆ”κ°€ν•œλ‹€. βœ…

        const sum = function (x, y) {
          return x + y;
        };
        
        const currySum = _.curry(sum);
        
        console.log(sum(10, 20));
        
        console.log(currySum(30)(40));
        

        μ•žμ„œ 03μ—μ„œ μ—΄μ‹¬νžˆ ν•¨μˆ˜λ₯Ό λ¦¬ν„΄ν•˜λŠ” λ°©μ‹μœΌλ‘œ 컀링을 직접 λ§Œλ“€μ—ˆμ§€λ§Œ,
        lodash의 _.curryλ₯Ό μ“°λ©΄ 이런 μ½”λ“œλ₯Ό μžλ™μœΌλ‘œ 컀링 ν•¨μˆ˜λ‘œ λ³€ν™˜ν•΄μ€€λ‹€.


    • μΊ‘μŠν™”

      • 객체 λ‚΄λΆ€μ—μ„œλ§Œ μ ‘κ·Ό κ°€λŠ₯ν•œ 속성을 λ§Œλ“€μ–΄ μ‚¬μš©ν•˜κ³  μ™ΈλΆ€μ—μ„œλŠ” ν•΄λ‹Ή 속성을 직접 μ ‘κ·Όν•˜μ§€ λͺ»ν•˜λ„둝 λ§Œλ“œλŠ” 객체지ν–₯ μ–Έμ–΄μ˜ νŠΉμ§•(C++, Javaμ—μ„œλŠ” private ν‚€μ›Œλ“œλ‘œ μ§€μ •κ°€λŠ₯)

      • ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ„ μ–Έν•œ μ§€μ—­λ³€μˆ˜λŠ” μ™ΈλΆ€μ—μ„œ μ ‘κ·Όν•˜μ§€ λͺ»ν•˜λŠ” 반면 λ‚΄λΆ€ λ©”μ„œλ“œμΈ ν΄λ‘œμ €μ—μ„œλŠ” μ ‘κ·Ό κ°€λŠ₯ν•˜λ‹€λŠ” νŠΉμ§•μ„ μ΄μš©ν•΄μ„œ κ΅¬ν˜„

      • ES2019μ—μ„œ class μ •μ˜μ‹œ 속성λͺ…μ΄λ‚˜ λ©”μ„œλ“œλͺ… μ•žμ— #을 뢙이면 ν•΄λ‹Ή class λ‚΄λΆ€μ—μ„œλ§Œ μ ‘κ·Ό κ°€λŠ₯ν•œ private 속성과 λ©”μ„œλ“œ μ •μ˜ κΈ°λŠ₯이 좔가됨

      • ex04-02.js

        // count 속성과 ride(), getCount() λ©”μ„œλ“œ μž‘μ„±
        const Counter = function () {
          this.count = 0;
          this.getCount = function () {
            return this.count;
          };
          this.ride = function () {
            this.count++;
          };
        };
        
        const c = new Counter();
        c.ride();
        c.ride();
        
        c.count += 40;
        
        console.log("전체 νƒ‘μŠΉμž", c.getCount()); 
        • βœ… ν˜„μž¬ μ½”λ“œμ˜ μ£Όμš” 문제점

          1. countλ₯Ό μ™ΈλΆ€μ—μ„œ 직접 μˆ˜μ • κ°€λŠ₯함 (μΊ‘μŠν™” μœ„λ°˜)
          • μ•„λž˜ μ½”λ“œμ²˜λŸΌ μ™ΈλΆ€μ—μ„œ countλ₯Ό 직접 μ‘°μž‘ν•  수 μžˆμ–΄:
            c.count += 40;
          • μ΄λ ‡κ²Œ 되면 ride() λ©”μ„œλ“œλ₯Ό μš°νšŒν•΄μ„œ 값을 λ³€κ²½ν•˜λŠ” 게 κ°€λŠ₯ν•˜λ‹ˆκΉŒ,λ‚΄λΆ€ 둜직의 신뒰성을 깨뜨리게 돼.
          • 예λ₯Ό λ“€μ–΄ λˆ„κ΅°κ°€ μ‹€μˆ˜λ‘œ c.count = -999처럼 λ°”κΎΈλ©΄ 전체 둜직이 λ¬΄λ„ˆμ§.
          1. 객체의 μƒνƒœ 관리가 ν—ˆμˆ ν•¨
          • ride() λ©”μ„œλ“œλŠ” countλ₯Ό 1μ”© μ¦κ°€μ‹œν‚€λŠ” 역할인데,μ™ΈλΆ€μ—μ„œ 직접 countλ₯Ό 바꿔버리면 ride() 호좜 여뢀와 무관해짐.
          • 즉, λ‚΄λΆ€ λ™μž‘ μΆ”μ μ΄λ‚˜ 디버깅이 μ–΄λ €μ›Œμ§€κ³ , "μ§„μ§œ λͺ‡ 번 νƒ”λŠ”κ°€?"λ₯Ό 보μž₯ν•  수 μ—†μŒ.

        // 계선점
        // count 속성과 ride(), getCount() λ©”μ„œλ“œ μž‘μ„±
        const Counter = function () {
          let count = 0;
          this.getCount = function () {
            return count;
          };
          this.ride = function () {
            if (count < 40) {
              count++;
            } else {
              console.log("정원이 μ΄ˆκ³Όλ˜μ—ˆμŠ΅λ‹ˆλ‹€.!");
            }
          };
        };
        
        const c = new Counter();
        c.ride();
        c.ride();
        
        for (let i = 0; i < 40; i++) {
          c.ride();
        }
        
        console.log("전체 νƒ‘μŠΉμž", c.getCount());
        
        • βœ… κ°œμ„ λœ 점

          1. countκ°€ ν΄λ‘œμ €λ‘œ 보호됨 (은닉화 성곡)
          • let count = 0;이 μƒμ„±μž ν•¨μˆ˜ 내뢀에 μ„ μ–Έλ˜μ–΄,μ™ΈλΆ€μ—μ„œλŠ” count에 직접 μ ‘κ·Όν•˜κ±°λ‚˜ μˆ˜μ •ν•  수 μ—†μŒ.
          • 이제 c.count += 40 같은 μ‘°μž‘μ€ λΆˆκ°€λŠ₯ν•˜κ³ , 였직 λ©”μ„œλ“œλ‘œλ§Œ μ‘°μž‘ κ°€λŠ₯함.
          1. λΆˆν•„μš”ν•œ μ „μ—­ λ³€μˆ˜ μ‚¬μš© 제거됨
            • forλ¬Έμ—μ„œ let i = 0을 μ‚¬μš©ν•΄, iκ°€ 블둝 μŠ€μ½”ν”„ λ³€μˆ˜κ°€ λ˜μ—ˆμŒ.
            • μ΄μ „μ—λŠ” iκ°€ μ „μ—­ λ³€μˆ˜λ‘œ 암묡 μ„ μ–Έλ˜μ–΄ λ‹€λ₯Έ μ½”λ“œμ— 영ν–₯을 쀄 수 μžˆμ—ˆμ§€λ§Œ,이젠 μ•ˆμ „ν•˜κ²Œ ν•΄λ‹Ή 블둝 μ•ˆμ—μ„œλ§Œ λ™μž‘ν•¨.
          2. 정원 μ œν•œ κΈ°λŠ₯ μΆ”κ°€λ‘œ μ•ˆμ •μ„± ν–₯상
          • ride() λ©”μ„œλ“œμ— count < 40 쑰건이 생겨, μ΅œλŒ€ νƒ‘μŠΉ 인원 μ œν•œ κ°€λŠ₯.
          • 초과 νƒ‘μŠΉ μ‹œ "정원이 μ΄ˆκ³Όλ˜μ—ˆμŠ΅λ‹ˆλ‹€.!" λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•˜κ³  μ¦κ°€ν•˜μ§€ μ•ŠμŒ.
          • 싀세계 쑰건(예: μ—˜λ¦¬λ² μ΄ν„° μΈμ›μ œν•œ λ“±)κ³Ό μœ μ‚¬ν•˜κ²Œ μ œμ–΄ κ°€λŠ₯함.
          1. μΊ‘μŠν™” + 둜직 μ œμ–΄ λ™μ‹œ 적용
          • λ‚΄λΆ€ μƒνƒœλŠ” μ™ΈλΆ€μ—μ„œ μˆ¨κΈ°λ©΄μ„œ, νƒ‘μŠΉ μ‘°κ±΄κΉŒμ§€ λ…Όλ¦¬μ μœΌλ‘œ μ œμ–΄ν•¨.
          • μ½”λ“œμ˜ 일관성, μ•ˆμ •μ„±, μœ μ§€λ³΄μˆ˜μ„± λͺ¨λ‘ ν–₯상됨.

    • Partial application

      • κΈ°μ‘΄ ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜ 쀑 일뢀λ₯Ό 미리 μ±„μ›Œλ‘” μƒνƒœμ˜ ν•¨μˆ˜

      • 컀링된 ν•¨μˆ˜λ₯Ό 일뢀 λ‹¨κ³„κΉŒμ§€λ§Œ ν˜ΈμΆœν•œ ν›„ λ°˜ν™˜λ°›μ€ ν•¨μˆ˜λ₯Ό λ‚˜μ€‘μ— λ‚˜λ¨Έμ§€ 인자λ₯Ό μ „λ‹¬ν•΄μ„œ μ‹€ν–‰

      • ex02-17-05.js

        // κΈ°μ‘΄ ex02-17-05.js
        var count = 0;
        const myObj = {
          count: 0,
          visit: function(){
            // 방문자λ₯Ό ν•œλͺ… μ¦κ°€μ‹œν‚¨λ‹€.
            this.count++; // this = myObj
            const visit2 = function(){
              this.count++; // this = window
            };
            visit2();
          },
        };
        
        myObj.visit(); // this = myObj
        myObj.visit();
        console.log('방문자수', myObj.count); // 2
        // λ³€κ²½λœ ex02-17-05.js
        var count = 0;
        const myObj = {
          count: 0,
          visit: function () {
            // 방문자λ₯Ό ν•œλͺ… μ¦κ°€μ‹œν‚¨λ‹€.
            this.count++; // this = myObj
            const visitN = function (n) {
              this.count += n; // this = window
            };
            visitN.call(this, 2); // countλ₯Ό 2λͺ… 증가 => 1 + 2 = 3
            visitN.call(this, 2); // countλ₯Ό 2λͺ… 증가 => 3 + 2 = 5
        
            const visit3 = visitN.bind(this, 3);
            visit3(); // conutλ₯Ό 3λͺ… 증가 => 5 + 3 = 8 
            visit3(); // conutλ₯Ό 3λͺ… 증가 => 8 + 3 => 11 
          },
        };
        
        myObj.visit(); // this = myObj => 11
        myObj.visit(); 
        // 11 β†’ 12(11 + 1) β†’ 14(12 + 2) β†’ 16(14 + 2) β†’ 19(16 + 3) β†’ 22(19 +3) 
        console.log("방문자수", myObj.count); // 22
        • βœ… μ–΄λ–»κ²Œ λ°”λ€Œμ—ˆλŠ”κ°€?

          ν•­λͺ©μ™Όμͺ½ μ½”λ“œμ˜€λ₯Έμͺ½ μ½”λ“œ
          λ‚΄λΆ€ ν•¨μˆ˜ 이름visit2 (λ§€κ°œλ³€μˆ˜ μ—†μŒ)visitN (λ§€κ°œλ³€μˆ˜ n μ‚¬μš© κ°€λŠ₯)
          호좜 방식그λƒ₯ 호좜 (visit2())call, bind μ‚¬μš©ν•΄ this λͺ…ν™•ν•˜κ²Œ μ„€μ •
          this 바인딩 λ¬Έμ œλ‚΄λΆ€ ν•¨μˆ˜μ—μ„œ thisλŠ” window (λ˜λŠ” undefined)call, bind둜 thisλ₯Ό λͺ…μ‹œμ μœΌλ‘œ myObj둜 μ„€μ •
          μœ μ—°μ„±λ°©λ¬Έμž 1λͺ…μ”© μ¦κ°€λ§Œ κ°€λŠ₯nλͺ…μ”© μœ λ™μ μœΌλ‘œ 증가 κ°€λŠ₯
          μž¬μ‚¬μš©μ„±μ—†μŒμžˆμŒ β†’ ν•¨μˆ˜ μž¬μ‚¬μš© κ°€λŠ₯ (visitN, visit3)

          • πŸ’‘ μ–΄λ–€ 점이 쒋은가?

            1. this 바인딩 문제 ν•΄κ²°
            • μ™Όμͺ½μ—μ„œλŠ” visit2()λ₯Ό 일반 ν•¨μˆ˜μ²˜λŸΌ ν˜ΈμΆœν•΄μ„œ thisκ°€ myObjκ°€ μ•„λ‹˜
            • 였λ₯Έμͺ½μ—μ„œλŠ” call, bindλ₯Ό μ‚¬μš©ν•΄ thisλ₯Ό myObj둜 κ³ μ •μ‹œμΌœ 문제 해결됨
            1. μœ μ—°ν•œ λ§€κ°œλ³€μˆ˜ 처리
            • μ™Όμͺ½μ€ 무쑰건 1μ”© 증가
            • 였λ₯Έμͺ½μ€ n을 전달할 수 μžˆμ–΄, 1λͺ…, 2λͺ…, 3λͺ… λ“± 자유둭게 μ„€μ • κ°€λŠ₯ β†’ visitN(this, 2) β†’ 방문자 2λͺ… 증가
            1. μž¬μ‚¬μš©μ„± ν–₯상
            • 였λ₯Έμͺ½μ˜ visitN은 λ²”μš© ν•¨μˆ˜λ‘œ μ—¬λŸ¬ μƒν™©μ—μ„œ μž¬μ‚¬μš© κ°€λŠ₯
            • bind둜 미리 this κ³ μ •ν•΄ λ§Œλ“  visit3은 λ‚˜μ€‘μ— 반볡 ν˜ΈμΆœν•˜κΈ°λ„ 쉬움
            1. μ½”λ“œ ν™•μž₯μ„± ν–₯상
            • ν•¨μˆ˜ ν•˜λ‚˜λ§Œ λ°”κΎΈλ©΄ μ—¬λŸ¬ 상황에 적용 κ°€λŠ₯ β†’ μœ μ§€λ³΄μˆ˜ μ‰¬μ›Œμ§
            • 이후 λ°©λ¬Έ 수λ₯Ό λ‘œκ·Έμ— μ €μž₯ν•˜κ±°λ‚˜ μ‘°κ±΄λΆ€λ‘œ μ œν•œν•  λ•Œλ„ μœ μš©ν•¨

          • πŸ“Œ ν•œμ€„ μš”μ•½
            πŸ‘‰ this 바인딩 문제λ₯Ό ν•΄κ²°ν•˜κ³ , λ§€κ°œλ³€μˆ˜λ₯Ό λ°›μ•„ μœ μ—°ν•˜κ³  μž¬μ‚¬μš© κ°€λŠ₯ν•œ ν•¨μˆ˜ ꡬ쑰둜 κ°œμ„ ν•œ 점이 핡심!

        • βœ… bind()λž€?
          bind()λŠ” ν•¨μˆ˜μ˜ this 값을 κ³ μ •ν•΄μ„œ μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œμ•Ό.
          단, λ°”λ‘œ μ‹€ν–‰λ˜μ§€λŠ” μ•Šκ³  κ³ μ •λœ thisλ₯Ό κ°€μ§„ μƒˆ ν•¨μˆ˜λ§Œ 리턴해!


          • 🧠 핡심 κ°œλ… 정리

          • bind()λŠ” κΈ°μ‘΄ ν•¨μˆ˜λ₯Ό λ³΅μ œν•˜λ©΄μ„œ thisλ₯Ό μ§€μ •ν•œ ν•¨μˆ˜λ‘œ λ§Œλ“¦

          • 원본 ν•¨μˆ˜λŠ” λ³€ν•˜μ§€ μ•ŠμŒ

          • μ–Έμ œ 쓰냐면?

            • λ‚˜μ€‘μ— ν˜ΈμΆœν•  λ•Œ thisκ°€ λ°”λ€Œμ§€ μ•Šλ„λ‘ 미리 κ³ μ •ν•˜κ³  싢을 λ•Œ
            • 이벀트 ν•Έλ“€λŸ¬λ‚˜ 콜백 ν•¨μˆ˜μ— λ„˜κΈΈ λ•Œ thisκ°€ κΌ¬μ΄λŠ” κ±Έ 막기 μœ„ν•΄
          • πŸ“Œ ν•œμ€„ μš”μ•½ (κ°•ν™” 버전)

            bind()λŠ” ν•¨μˆ˜μ˜ thisλ₯Ό νŠΉμ • 객체둜 κ³ μ •ν•œ μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•΄, λ‚˜μ€‘μ— ν˜ΈμΆœν•  λ•Œλ„ thisκ°€ λ°”λ€Œμ§€ μ•Šλ„λ‘ 보μž₯ν•œλ‹€.


    • λ©”λͺ¨μ΄μ œμ΄μ…˜

      • ν΄λ‘œμ €κ°€ ν•„μš” μ—†μŒ

      • λ©”λͺ¨μ΄μ œμ΄μ…˜ 예제

      • ex02-23.js, ex04-05.js

        // ex02-23.js
        const isPrime = function (num) {
          isPrime._cache = isPrime._cache || {};
        
          if (isPrime._cache[num] !== undefined) {
            return isPrime._cache[num];
          }
        
          let prime = "맞음";
          for (let i = 2; i <= Math.sqrt(num); i++) {
            if (num % i === 0) {
              prime = "μ•„λ‹˜";
              break;
            }
          }
          isPrime._cache[num] = prime;
          return prime;
        };
        
        console.time("μ†Œμš”μ‹œκ°„");
        console.log("3 -> ", isPrime(3));
        console.log("4 -> ", isPrime(4));
        console.log("5 -> ", isPrime(5));
        console.log("6 -> ", isPrime(6));
        console.log("7 -> ", isPrime(7));
        console.log("8 -> ", isPrime(8));
        console.log("9 -> ", isPrime(9));
        console.log("1000000007 -> ", isPrime(1000000007));
        console.log("1000000007 -> ", isPrime(1000000007));
        console.log("1000000007 -> ", isPrime(1000000007));
        console.timeEnd("μ†Œμš”μ‹œκ°„");
        
        // ex04-05.js
        Function.prototype.memo = function (key) {
          this._cache = this._cache || {};
        
          if (this._cache[key] !== undefined) {
            return this._cache[key];
          } else {
            return (this._cache[key] = this(key));
          }
        };
        
        const isPrime = function (num) {
          let prime = "맞음";
        
          for (let i = 2; i < num; i++) {
            if (num % i === 0) {
              prime = "μ•„λ‹˜";
              break;
            }
          }
        
          return prime;
        };
        
        console.time("μ†Œμš”μ‹œκ°„");
        console.log("3 -> ", isPrime(3));
        console.log("4 -> ", isPrime(4));
        console.log("5 -> ", isPrime(5));
        console.log("6 -> ", isPrime(6));
        console.log("7 -> ", isPrime(7));
        console.log("8 -> ", isPrime(8));
        console.log("9 -> ", isPrime(9));
        console.log("1000000007 -> ", isPrime.memo(1000000007)); // 첫번째 캐싱
        console.log("1000000007 -> ", isPrime.memo(1000000007)); // 2번째 캐싱
        console.log("1000000007 -> ", isPrime.memo(1000000007)); // 3번째 캐싱
        console.timeEnd("μ†Œμš”μ‹œκ°„");
        
        isPrime.memo(3)
        β”‚
        β”œβ”€> memo λ©”μ„œλ“œ μ‹€ν–‰
        β”‚    β”œβ”€> μΊμ‹œ 확인/μ΄ˆκΈ°ν™”
        β”‚    β”œβ”€> μΊμ‹œμ— 3이 μ—†μœΌλ―€λ‘œ
        β”‚    β”‚    └─> isPrime(3) μ‹€ν–‰
        β”‚    β”‚         └─> μ†Œμˆ˜ νŒλ³„ ν›„ true λ°˜ν™˜
        β”‚    └─> μΊμ‹œμ— μ €μž₯ ν›„ true λ°˜ν™˜
        β”‚
        isPrime(3)
        └─> isPrime ν•¨μˆ˜ λ°”λ‘œ μ‹€ν–‰
              └─> μ†Œμˆ˜ νŒλ³„ ν›„ true λ°˜ν™˜
        • βœ… κ°œμ„ λœ 점 μš”μ•½

          1. λ©”λͺ¨μ΄μ œμ΄μ…˜ λ‘œμ§μ„ ν•¨μˆ˜ λ°–μœΌλ‘œ 뢄리 (μž¬μ‚¬μš© κ°€λŠ₯μ„± 증가)

            • πŸ”½ μ™Όμͺ½: isPrime ν•¨μˆ˜ μ•ˆμ—μ„œ _cache 관리
            • πŸ”Ό 였λ₯Έμͺ½: Function.prototype.memo둜 λ©”λͺ¨μ΄μ œμ΄μ…˜μ„ μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜ν™” β†’ λ‹€λ₯Έ ν•¨μˆ˜μ—μ„œλ„ .memo() 호좜만으둜 μΊμ‹œ κΈ°λŠ₯을 κ°„νŽΈν•˜κ²Œ μ“Έ 수 있음
          2. κ΄€μ‹¬μ‚¬μ˜ 뢄리 (κΈ°λŠ₯ λΆ„λ¦¬λ‘œ 가독성 ν–₯상)

            • μ™Όμͺ½μ€ μ†Œμˆ˜ νŒλ³„ 둜직 + μΊμ‹œ 둜직이 λ’€μ„žμ—¬ 있음
            • 였λ₯Έμͺ½μ€ isPrime은 였직 μ†Œμˆ˜ νŒλ³„λ§Œ, memoλŠ” μΊμ‹±λ§Œ μ²˜λ¦¬ν•΄μ„œ μ½”λ“œ 역할이 λͺ…ν™•νžˆ λ‚˜λ‰¨
          3. μ½”λ“œ μž¬μ‚¬μš©μ„± 증가

            • Function.prototype.memoλ₯Ό λͺ¨λ“  ν•¨μˆ˜μ—μ„œ μ‚¬μš©ν•  수 있음:

              const slowFn = (x) => { ... };
              slowFn.memo(x); // 캐싱 μžλ™ 처리
          4. ν•¨μˆ˜ μ •μ˜κ°€ 더 μˆœμˆ˜ν•΄μ§ (Pure Functionν™”)

            • isPrime은 μΊμ‹œλ‚˜ μ™ΈλΆ€ μƒνƒœ 없이 였직 인자만으둜 λ™μž‘
            • 이둜 인해 ν…ŒμŠ€νŠΈ, 디버깅, μž¬μ‚¬μš©μ΄ 훨씬 μ‰¬μ›Œμ§
          5. μ½”λ“œμ˜ ν™•μž₯μ„± ν–₯상

            • 이후 memo()에 만료 μ‹œκ°„, μΊμ‹œ 크기 μ œν•œ 같은 κΈ°λŠ₯도 μ‰½κ²Œ μΆ”κ°€ κ°€λŠ₯
            • κ°œλ³„ ν•¨μˆ˜ μˆ˜μ • 없이 λ©”λͺ¨μ΄μ œμ΄μ…˜ 정책을 μ „μ—­μ—μ„œ 관리할 수 있음

          πŸ“Œ ν•œ 쀄 μš”μ•½

          κΈ°λŠ₯ 뢄리 + μž¬μ‚¬μš©μ„± + μœ μ§€λ³΄μˆ˜μ„± + ν™•μž₯μ„±κΉŒμ§€ λͺ¨λ‘ μ’‹μ•„μ§„ ꡬ쑰!

        • μ„€λͺ…

          // ex04-05.js
          Function.prototype.memo = function (key) {
            this._cache = this._cache || {};
          
            if (this._cache[key] !== undefined) {
              return this._cache[key];
            } else {
              return (this._cache[key] = this(key));
            }
          };
          
          const isPrime = function (num) {
            let prime = "맞음";
            for (let i = 2; i < num; i++) {
              if (num % i === 0) {
                prime = "μ•„λ‹˜";
                break;
              }
            }
            return prime;
          };
          
          const sayHello = function (name) {
            return "Hello" + name;
          };
          
          console.log(sayHello("캐싱 μ•ˆν•¨"));
          console.log(sayHello.memo("캐싱 함"));
          console.log(sayHello.memo("캐싱 함"));
          
          console.time("μ†Œμš”μ‹œκ°„");
          
          console.log("3 -> ", isPrime(3));
          console.log("4 -> ", isPrime(4));
          console.log("5 -> ", isPrime(5));
          console.log("6 -> ", isPrime(6));
          console.log("7 -> ", isPrime(7));
          console.log("8 -> ", isPrime(8));
          console.log("9 -> ", isPrime(9));
          
          console.log("1000000007 -> ", isPrime.memo(1000000007));
          console.log("1000000007 -> ", isPrime.memo(1000000007));
          console.log("1000000007 -> ", isPrime.memo(1000000007));
          
          console.timeEnd("μ†Œμš”μ‹œκ°„");
          
          • 1️⃣ 1. Function.prototype.memo = function (key) { ... }

            πŸ“Œ 핡심 κΈ°λŠ₯

            λͺ¨λ“  ν•¨μˆ˜μ— κ³΅ν†΅μ μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλŠ” λ©”λͺ¨μ΄μ œμ΄μ…˜ κΈ°λŠ₯을 좔가함

            this._cacheλ₯Ό 톡해 ν•¨μˆ˜ λ‹¨μœ„λ‘œ μΊμ‹œ 객체λ₯Ό μ €μž₯

            같은 μž…λ ₯이 λ“€μ–΄μ˜€λ©΄ κ²°κ³Όλ₯Ό λ‹€μ‹œ κ³„μ‚°ν•˜μ§€ μ•Šκ³  μΊμ‹œλœ κ°’ λ°˜ν™˜

          • 2️⃣ sayHello.memo("캐싱 함")

            πŸ“Œ μ—­ν• 

            • sayHello("캐싱 함")을 졜초 ν•œ 번 계산 ν›„ μΊμ‹œμ— μ €μž₯
            • 두 λ²ˆμ§ΈλΆ€ν„°λŠ” μƒˆλ‘œ κ³„μ‚°ν•˜μ§€ μ•Šκ³  μ €μž₯된 κ²°κ³Όλ₯Ό λ°˜ν™˜

            🧩 포인트

            • "캐싱 함" β†’ λ‚΄λΆ€μ μœΌλ‘œ sayHello._cache["캐싱 함"]에 μ €μž₯됨
            • 결과적으둜 λΆˆν•„μš”ν•œ 계산을 쀄여 μ„±λŠ₯ ν–₯상

          • 3️⃣ isPrime.memo(1000000007)

            πŸ“Œ μ—­ν• 
            μ†Œμˆ˜ νŒλ³„ ν•¨μˆ˜ isPrime에 λŒ€ν•΄ κ³ λΉ„μš© 계산을 λ©”λͺ¨μ΄μ œμ΄μ…˜μœΌλ‘œ μ΅œμ ν™”

            1000000007은 맀우 큰 μˆ˜μ΄λ―€λ‘œ 첫 계산에 μ‹œκ°„μ΄ 였래 κ±Έλ¦Ό

            이후 λ™μΌν•œ μž…λ ₯에 λŒ€ν•΄μ„  μ¦‰μ‹œ μΊμ‹œλœ κ°’ λ°˜ν™˜


          🧩 정리: κ°•μ‘°λœ λΆ€λΆ„μ˜ 의미

          λ²ˆν˜Έμ½”λ“œμ„€λͺ…
          1️⃣Function.prototype.memoλͺ¨λ“  ν•¨μˆ˜μ— μΊμ‹œ κΈ°λŠ₯ λΆ€μ—¬
          2️⃣sayHello.memo(...)λ‹¨μˆœ λ¬Έμžμ—΄ λ°˜ν™˜ ν•¨μˆ˜λ„ 캐싱 κ°€λŠ₯
          3️⃣isPrime.memo(...)κ³ λΉ„μš© μ—°μ‚°μ˜ 캐싱 효과λ₯Ό λ³΄μ—¬μ£ΌλŠ” 사둀

πŸ”— λ°°μ› λ˜ 파일


❓ 생긴 질문 / 더 μ•Œμ•„λ³Ό 것

  • μ•„..였늘 λ°°μ› λ˜κ±° λ„ˆλ¬΄ μ–΄λ ΅λ‹€... μ„ μƒλ‹˜κ»˜μ„œ 였늘 배운거 μ–΄λ €μš΄ κ°œλ…μ΄λΌκ³  ν•˜λŠ”λ° μ§„μ§œ~ λ„ˆλ¬΄ μ–΄λ €μ› λ‹€... μ§ˆλ¬Έλ„ 막 ν•˜κ³  싢은데 아직 지식이 μ—†λŠ”μ§€ 질문이 λ– μ˜€λ₯΄μ§„ μ•Šμ•˜λ‹€..

πŸ”— μ°Έκ³  자료

profile
front-endλ₯Ό κΏˆκΏ‰λ‹ˆλ‹€

0개의 λŒ“κΈ€