Chapter 8: The Module Pattern - hochan222/Everything-in-JavaScript GitHub Wiki

Encapsulation and Least Exposure (POLE)

์บก์Šํ™”๋Š” ์ข…์ข… ๊ฐ์ฒด ์ง€ํ–ฅ (OO) ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์›์น™์œผ๋กœ ์ธ์šฉ๋˜์ง€๋งŒ ๊ทธ๋ณด๋‹ค ๋” ๊ธฐ๋ณธ์ ์ด๊ณ  ๊ด‘๋ฒ”์œ„ํ•˜๊ฒŒ ์ ์šฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์บก์Šํ™”์˜ ๋ชฉํ‘œ๋Š” ํ•จ๊ป˜ ๊ณตํ†ต ๋ชฉ์ ์„ ์ œ๊ณตํ•˜๋Š” ์ •๋ณด(๋ฐ์ดํ„ฐ) ๋ฐ ๋™์ž‘(ํ•จ์ˆ˜)์˜ ๋ฒˆ๋“ค๋ง ๋˜๋Š” ๊ณต๋™ ๋ฐฐ์น˜์ž…๋‹ˆ๋‹ค.

Namespaces (Stateless Grouping)

// namespace, not module
var Utils = { 
  cancelEvt(evt) {
    evt.preventDefault(); 
    evt.stopPropagation(); 
    evt.stopImmediatePropagation();
  }, 
  wait(ms) {
    return new Promise(function c(res){ 
      setTimeout(res,ms);
    }); 
  },
  isValidEmail(email) {
    return /[^@]+@[^@.]+\.[^@.]+/.test(email);
  } 
};

Data Structures (Stateful Grouping)

// data structure, not module
var Student = { 
    records: [
        { id: 14, name: "Kyle", grade: 86 },
        { id: 73, name: "Suzy", grade: 87 },
        { id: 112, name: "Frank", grade: 75 },
        { id: 6, name: "Sarah", grade: 91 }
    ],
    getName(studentID) {
        var student = this.records.find( 
            student => student.id == studentID
        );
        return student.name; 
    }
}; 

Student.getName(73);
// Suzy

Modules (Stateful Access Control)

var Student = (function defineStudent(){ 
    var records = [
        { id: 14, name: "Kyle", grade: 86 },
        { id: 73, name: "Suzy", grade: 87 },
        { id: 112, name: "Frank", grade: 75 },
        { id: 6, name: "Sarah", grade: 91 }
    ];

    var publicAPI = { 
        getName
    };
    return publicAPI;

    // ************************

    function getName(studentID) { 
        var student = records.find(
            student => student.id == studentID );
        return student.name; 
    }
})();

Student.getName(73); // Suzy

์–ดํœ˜ ๋ฒ”์œ„๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด ์™ธ๋ถ€ ๋ชจ๋“ˆ ์ •์˜ ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๊ฒƒ์ด ๋น„๊ณต๊ฐœ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜์—์„œ ๋ฐ˜ํ™˜ ๋œ ๊ณต์šฉ API ๊ฐœ์ฒด์— ์ถ”๊ฐ€ ๋œ ์†์„ฑ ๋งŒ ์™ธ๋ถ€ ๊ณต์šฉ ์‚ฌ์šฉ์„ ์œ„ํ•ด ๋‚ด๋ณด๋‚ด์ง‘๋‹ˆ๋‹ค. iife์˜ ์‚ฌ์šฉ์€ ์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์ด ์ผ๋ฐ˜์ ์œผ๋กœ "์‹ฑ๊ธ€ ํ†ค"์ด๋ผ๊ณ ํ•˜๋Š” ์ค‘์•™ ๋ชจ๋“ˆ์˜ ๋‹จ์ผ ์ธ์Šคํ„ด์Šค๋งŒ ํ•„์š”ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

Module Factory (Multiple Instances)

// factory function, not singleton IIFE
function defineStudent() { 
    var records = [
        { id: 14, name: "Kyle", grade: 86 },
        { id: 73, name: "Suzy", grade: 87 },
        { id: 112, name: "Frank", grade: 75 },
        { id: 6, name: "Sarah", grade: 91 }
    ];

    var publicAPI = { 
        getName
    };

    return publicAPI;
// ************************ 

    function getName(studentID) {
        var student = records.find(
            student => student.id == studentID
        );
        return student.name; 
    }
}`

var fullTime = defineStudent();
fullTime.getName(73);  // Suzy

Node CommonJS Modules


module.exports.getName = getName;

// ************************

var records = [
    { id: 14, name: "Kyle", grade: 86 }, 
    { id: 73, name: "Suzy", grade: 87 }, 
    { id: 112, name: "Frank", grade: 75 }, 
    { id: 6, name: "Sarah", grade: 91 }
];

function getName(studentID) { 
    var student = records.find(
        student => student.id == studentID 
    );

    return student.name;
}

// defining a new object for the API
module.exports = { 
  // ..exports..
};

์ด๊ฒƒ๋ณด๋‹ค๋Š” ์–•์€ ๋ณต์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์•„๋ž˜๋กœ ์‚ฌ์šฉํ•ฉ์‹œ๋‹ค.

Object.assign(module.exports,{ 
  // .. exports ..
});

์ ‘๊ทผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

var getName = require("/path/to/student.js").getName; 
// or alternately:
var { getName } = require("/path/to/student.js");

Node์—์„œ require๋Š” ์ ˆ๋Œ€๊ฒฝ๋กœ๋ฅผ ์ฐพ์€ ๋’ค node_modules์—์„œ ์ฐพ์Šต๋‹ˆ๋‹ค.

Modern ES Modules (ESM)

export { getName };

// ************************

var records = [
    { id: 14, name: "Kyle", grade: 86 }, 
    { id: 73, name: "Suzy", grade: 87 }, 
    { id: 112, name: "Frank", grade: 75 }, 
    { id: 6, name: "Sarah", grade: 91 }
];

function getName(studentID) {
    var student = records.find(
        student => student.id == studentID 
    );
    return student.name; 
}
export function getName(studentID) { 
  // ..
}
export default function getName(studentID) { 
  // ..
}

๋‹ค์Œ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ ์“ฐ๋Š” ์ฝ”๋“œ ์ž…๋‹ˆ๋‹ค.

import { getName } from "/path/to/students.js";
getName(73);   // Suzy

import { getName as getStudentName } from "/path/to/students.js";
getStudentName(73); // Suzy

๋งŒ์•ฝ default export๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import getName from "/path/to/students.js";
getName(73);   // Suzy