ํด๋ก์
ํด๋ก์ ๋ ์ฃผ๋ณ ์ํ(์ดํ์ ํ๊ฒฝ)์ ๋ํ ์ฐธ์กฐ์ ํจ๊ป ๋ฌถ์ธ(ํฌํจ๋) ํจ์์ ์กฐํฉ์ ๋๋ค. ์ฆ, ํด๋ก์ ๋ ๋ด๋ถ ํจ์์์ ์ธ๋ถ ํจ์์ ๋ฒ์์ ๋ํ ์ ๊ทผ์ ์ ๊ณตํฉ๋๋ค. JavaScript์์ ํด๋ก์ ๋ ํจ์ ์์ฑ ์ ํจ์๊ฐ ์์ฑ๋ ๋๋ง๋ค ์์ฑ๋ฉ๋๋ค.
์ดํ์ ๋ฒ์ ์ง์ (Lexical scoping)
๋ค์์ ๊ณ ๋ คํด ๋ด ์๋ค.
function init() {
var name = "Mozilla"; // name์ init์ ์ํด ์์ฑ๋ ์ง์ญ ๋ณ์์ด๋ค.
function displayName() {
// displayName() ์ ๋ด๋ถ ํจ์์ด๋ฉฐ, ํด๋ก์ ๋ค.
console.log(name); // ๋ถ๋ชจ ํจ์์์ ์ ์ธ๋ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ค.
}
displayName();
}
init();
init()์ ์ง์ญ ๋ณ์ name๊ณผ ํจ์ displayName()์ ์์ฑํฉ๋๋ค. displayName()์
init() ์์ ์ ์๋ ๋ด๋ถ ํจ์์ด๋ฉฐ init() ํจ์ ๋ณธ๋ฌธ์์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ ์ฃผ์ํ ์ ์ displayName() ๋ด๋ถ์ ์์ ๋ง์ ์ง์ญ ๋ณ์๊ฐ ์๋ค๋ ์ ์
๋๋ค. ๊ทธ๋ฌ๋, ๋ด๋ถ ํจ์์์ ์ธ๋ถ ํจ์์ ๋ณ์์ ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์, displayName() ์ญ์ ๋ถ๋ชจ ํจ์ init()์์ ์ ์ธ๋ ๋ณ์ name์ ์ ๊ทผํ ์ ์์ต๋๋ค.
์ด JSFiddle ๋งํฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ์คํํ๊ณ displayName() ํจ์ ๋ด์ console.log() ๋ฌธ์ด ์ฑ๊ณต์ ์ผ๋ก ๋ถ๋ชจ ํจ์ ๋ด์์ ์ ์ธ๋ name ๊ฐ์ ํ์ํ๋์ง ํ์ธํฉ๋๋ค.
์ด๊ฒ์ ํจ์๊ฐ ์ค์ฒฉ๋ ๋ ๊ตฌ๋ฌธ ๋ถ์๊ธฐ๊ฐ ๋ณ์ ์ด๋ฆ์ ํ์ธํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํ๋ '์ ์ ์ค์ฝํ'์ ์์์ ๋๋ค. ์ฌ๊ธฐ์ '์ ์ '์ด๋, ์ ์ ๋ฒ์ ์ง์ ๊ณผ์ ์์ ๋ณ์๊ฐ ์ด๋์์ ์ฌ์ฉ ๊ฐ๋ฅํ์ง ์๊ธฐ ์ํด ๊ทธ ๋ณ์๊ฐ ์์ค์ฝ๋ ๋ด ์ด๋์์ ์ ์ธ๋์๋์ง ๊ณ ๋ คํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋๋ฐ, ๋จ์ด '์ ์ '์ ์ด๋ฐ ์ฌ์ค์ ๋ํ๋ ๋๋ค. ์ค์ฒฉ๋ ํจ์๋ ์ธ๋ถ ๋ฒ์์์ ์ ์ธํ ๋ณ์์๋ ์ ๊ทผํ ์ ์์ต๋๋ค.
์ด ํน์ ์์์์, ๋ฒ์๋ "ํจ์ ๋ฒ์"๋ผ๊ณ ํ๋๋ฐ, ๊ทธ ์ด์ ๋ ๋ณ์์ ์ ๊ทผํ ์ ์๊ณ ๋ณ์๊ฐ ์ ์ธ๋ ํจ์ ๋ณธ๋ฌธ ๋ด์์๋ง ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
let๊ณผ const๋ฅผ ์ฌ์ฉํ ๋ฒ์ ์ง์
(ES6 ์ด์ ) ์ ํต์ ์ธ JavaScript์๋ ํจ์ ์ค์ฝํ์ ์ ์ญ ์ค์ฝํ ๋ ๊ฐ์ง๋ง ์กด์ฌํ์ต๋๋ค. var๋ก ์ ์ธํ ๋ณ์๋ ํจ์ ๋ด๋ถ ๋๋ ์ธ๋ถ์์ ์ ์ธ๋์๋์ง์ ๋ฐ๋ผ ํจ์ ์ค์ฝํ ๋๋ ์ ์ญ ์ค์ฝํ๋ฅผ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค. ์ด๋, ์ค๊ดํธ๋ก ํ์๋ ๋ธ๋ก์ด ์ค์ฝํ๋ฅผ ์์ฑํ์ง ์๋๋ค๋ ์ ์์ ํผ๋์ ์ผ์ผํฌ ์ ์์ต๋๋ค.
if (Math.random() > 0.5) {
var x = 1;
} else {
var x = 2;
}
console.log(x);
C๋ Java์ ๊ฐ์ด ๋ธ๋ก์ด ์ค์ฝํ๋ฅผ ์์ฑํ๋ ์ธ์ด์ ๊ฒฝ์ฐ, ์ ์ฝ๋์ console.log ๋ผ์ธ์์ x๊ฐ ์ด๋ค ๋ธ๋ก ์ค์ฝํ์๋ ํฌํจ๋์ง ์๊ธฐ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋ฐ์ํด์ผ ํ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋, ๋ธ๋ก์ var๋ก ์ ์ธํ ๋ณ์์ ๋ํด ์ค์ฝํ๋ฅผ ์์ฑํ์ง ์๊ธฐ ๋๋ฌธ์, ์ฌ๊ธฐ์ var ๋ช
๋ น๋ฌธ์ ์ ์ญ ๋ณ์๋ฅผ ์์ฑํฉ๋๋ค. ์ด๊ฒ์ ํด๋ก์ ์ ํจ๊ป ์ฌ์ฉํ์ ๋ ์ด๋ค ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ ์๋์ง ์ค์ ์์ ๊ฐ ์๋ ์๊ฐ๋์ด ์์ต๋๋ค.
ES6์์, JavaScript๋ ๋ธ๋ก ์ค์ฝํ ๋ณ์๋ฅผ ์์ฑํ ์ ์๋๋ก let๊ณผ const ์ ์ธ๊ณผ ํจ๊ป ์ผ์์ ์ฌ๊ฐ์ง๋ ๋ฑ์ ๋์
ํ์ต๋๋ค.
if (Math.random() > 0.5) {
const x = 1;
} else {
const x = 2;
}
console.log(x); // ์ฐธ์กฐ ์๋ฌ: x๊ฐ ์ ์๋์ด ์์ง ์์ต๋๋ค.
์์ฝํ์๋ฉด, ES6๋ถํฐ ๋ธ๋ก์ ์ค์ฝํ๋ก ์ทจ๊ธ๋๊ธฐ ์์ํ์ง๋ง, ์ด๋ let๊ณผ const๋ก ๋ณ์๋ฅผ ์ ์ธํ์ ๋๋ง ์ ํจํฉ๋๋ค. ๋ํ, ES6์์ ๋ชจ๋์ ๋์
ํ๋ฉด์ ๋ ๋ค๋ฅธ ์ค์ฝํ๋ฅผ ์ ๊ณตํ๊ฒ ๋์์ต๋๋ค. ์ถํ ์๊ฐํ๊ฒ ์ง๋ง, ํด๋ก์ ๋ ์ด ๋ชจ๋ ์ค์ฝํ์ ๋ณ์๋ฅผ ์บก์ฒํ ์ ์์ต๋๋ค.
ํด๋ก์ (Closure)
๋ค์ ์์ ๋ฅผ ๋ณด๊ฒ ์ต๋๋ค.
function makeFunc() {
const name = "Mozilla";
function displayName() {
console.log(name);
}
return displayName;
}
const myFunc = makeFunc();
myFunc();
์ด ์ฝ๋๋ ์ ์์ ์ init() ํจ์์ ์์ ํ ๋์ผํ ๊ฒฐ๊ณผ๊ฐ ์คํ๋ฉ๋๋ค. ๋ค๋ฅธ ์ (๊ทธ๋ฆฌ๊ณ ํฅ๋ฏธ๋ก์ด ์ )์ displayName() ๋ด๋ถ ํจ์๊ฐ ์คํ๋๊ธฐ ์ ์ ์ธ๋ถ ํจ์์์ ๋ฐํ๋๋ค๋ ์ ์
๋๋ค.
ํ๋์ ๋ด์๋, ์ด ์ฝ๋๊ฐ ์ฌ์ ํ ์๋ํ๋ ๊ฒ์ด ์ง๊ด์ ์ผ๋ก ๋ณด์ด์ง ์์ ์ ์์ต๋๋ค. ๋ช๋ช ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์, ํจ์ ์์ ์ง์ญ ๋ณ์๋ค์ ๊ทธ ํจ์๊ฐ ์ฒ๋ฆฌ๋๋ ๋์์๋ง ์กด์ฌํฉ๋๋ค. makeFunc() ์คํ์ด ๋๋๋ฉด, name ๋ณ์์ ๋ ์ด์ ์ ๊ทผํ ์ ์๊ฒ ๋ ๊ฒ์ผ๋ก ์์ํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด์ง๋ง, ์ฝ๋๋ ์ฌ์ ํ ์์๋๋ก ์๋ํ๊ธฐ ๋๋ฌธ์ JavaScript์์๋ ๋ถ๋ช
ํ ๋ค๋ฆ
๋๋ค.
๊ทธ ์ด์ ๋ JavaScript์ ํจ์๊ฐ ํด๋ก์ ๋ฅผ ํ์ฑํ๊ธฐ ๋๋ฌธ์
๋๋ค. ํด๋ก์ ๋ ํจ์์ ํจ์๊ฐ ์ ์ธ๋ ์ดํ์ ํ๊ฒฝ์ ์กฐํฉ์
๋๋ค. ์ด ํ๊ฒฝ์ ํด๋ก์ ๊ฐ ์์ฑ๋ ์์ ์ ์ ํจ ๋ฒ์ ๋ด์ ์๋ ๋ชจ๋ ์ง์ญ ๋ณ์๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์์์ ๊ฒฝ์ฐ, myFunc์ makeFunc์ด ์คํ
๋ ๋ ์์ฑ๋ displayName ํจ์์ ์ธ์คํด์ค์ ๋ํ ์ฐธ์กฐ์
๋๋ค. displayName์ ์ธ์คํด์ค๋ ๋ณ์ name ์ด ์๋ ์ดํ์ ํ๊ฒฝ์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ์งํฉ๋๋ค. ์ด๋ฐ ์ด์ ๋ก, myFunc๊ฐ ํธ์ถ๋ ๋ ๋ณ์ name์ ์ฌ์ฉํ ์ ์๋ ์ํ๋ก ๋จ๊ฒ ๋๊ณ "Mozilla" ๊ฐ console.log ์ ์ ๋ฌ๋ฉ๋๋ค.
๋ค์์ ์กฐ๊ธ ๋ ํฅ๋ฏธ๋ก์ด ์์ ์ธ makeAdder ํจ์์
๋๋ค.
function makeAdder(x) {
return function (y) {
return x + y;
};
}
const add5 = makeAdder(5);
const add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
์ด ์์ ์์, ๋จ์ผ ์ธ์ x๋ฅผ ๋ฐ์์ ์ ํจ์๋ฅผ ๋ฐํํ๋ ํจ์ makeAdder(x)๋ฅผ ์ ์ํฉ๋๋ค. ๋ฐํ๋๋ ํจ์๋ ๋จ์ผ์ธ์ y๋ฅผ ๋ฐ์์ x์ y์ ํฉ์ ๋ฐํํฉ๋๋ค.
๋ณธ์ง์ ์ผ๋ก, makeAdder๋ ํจ์๋ฅผ ๋ง๋ค์ด๋ด๋ ํฉํ ๋ฆฌ์
๋๋ค. ์ด๋ makeAdderํจ์๊ฐ ํน์ ํ ๊ฐ์ ์ธ์๋ก ๊ฐ์ง ์ ์๋ ํจ์๋ค์ ๋ฆฌํดํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์์ ์์ ์์, ํจ์ ํฉํ ๋ฆฌ๋ ์ธ์์ 5์ 10์ ๋ํ๋ ๋ ๊ฐ์ ์๋ก์ด ํจ์๋ค์ ๋ง๋ค์ด ๋
๋๋ค.
add5์ add10์ ๋ ๋ค ํด๋ก์ ์
๋๋ค. ์ด๋ค์ ๊ฐ์ ํจ์ ๋ณธ๋ฌธ ์ ์๋ฅผ ๊ณต์ ํ์ง๋ง ์๋ก ๋ค๋ฅธ ๋งฅ๋ฝ(์ดํ)์ ํ๊ฒฝ์ ์ ์ฅํฉ๋๋ค. ํจ์ ์คํ ์ add5์ ์ดํ์ ํ๊ฒฝ์์, ํด๋ก์ ๋ด๋ถ์ x๋ 5 ์ด์ง๋ง, add10์ ๋งฅ๋ฝ์ ํ๊ฒฝ์์ x๋ 10์
๋๋ค.
์ค์ฉ์ ์ธ ํด๋ก์
ํด๋ก์ ๋ ์ด๋ค ๋ฐ์ดํฐ(์ดํ์ ํ๊ฒฝ)์ ๊ทธ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ํ๋ ํจ์๋ฅผ ์ฐ๊ด์์ผ์ฃผ๊ธฐ ๋๋ฌธ์ ์ ์ฉํฉ๋๋ค. ์ด๊ฒ์ ๊ฐ์ฒด๊ฐ ์ด๋ค ๋ฐ์ดํฐ์(๊ทธ ๊ฐ์ฒด์ ์์ฑ) ํ๋ ํน์ ๊ทธ ์ด์์ ๋ฉ์๋๋ค์ ์ฐ๊ด์ํจ๋ค๋ ์ ์์ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ๊ณผ ๋ถ๋ช ํ ๊ฐ์ ๋งฅ๋ฝ์ ์์ต๋๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก, ์ค์ง ํ๋์ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ฒด๋ฅผ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ ๋ชจ๋ ๊ณณ์ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด๋ ๊ฒ ํ ์ ์๋ ์ํฉ์ ํนํ ์น์์ ์ผ๋ฐ์ ์ ๋๋ค. ํ๋ก ํธ์๋ JavaScript์์ ์ฐ๋ฆฌ๊ฐ ์ฐ๋ ๋ง์ ์ฝ๋๊ฐ ์ด๋ฒคํธ ๊ธฐ๋ฐ์ ๋๋ค. ์ฐ๋ฆฌ๋ ๋ช ๊ฐ์ง ๋์์ ์ ์ํ ๋ค์ ์ฌ์ฉ์์ ์ํ ์ด๋ฒคํธ(ํด๋ฆญ ํน์ ํค ๋๋ฅด๊ธฐ ๊ฐ์)์ ์ฐ๊ฒฐํฉ๋๋ค. ์ด ์ฝ๋๋ ์ผ๋ฐ์ ์ผ๋ก ์ฝ๋ฐฑ(์ด๋ฒคํธ์ ์๋ตํ์ฌ ์คํ๋๋ ๋จ์ผ ํจ์)์ผ๋ก ์ถ๊ฐ๋ฉ๋๋ค.
์๋ฅผ ๋ค๋ฉด, ํ์ด์ง์ ๊ธ์ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ๋ ๋ช ๊ฐ์ ๋ฒํผ์ ์ถ๊ฐํ๋ค๊ณ ๊ฐ์ ํฉ์๋ค. ์ด ์์
์ ์ํํ๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ body ์์์ font-size๋ฅผ ํฝ์
๋จ์๋ก ์ง์ ํ๊ณ ์๋์ ์ธ em ๋จ์๋ฅผ ์ฌ์ฉํ์ฌ ํ์ด์ง์ ๋ค๋ฅธ ์์(์: ํค๋)์ ํฌ๊ธฐ๋ฅผ ์ค์ ํ๋ ๊ฒ์
๋๋ค.
body {
font-family: Helvetica, Arial, sans-serif;
font-size: 12px;
}
h1 {
font-size: 1.5em;
}
h2 {
font-size: 1.2em;
}
์ฐ๋ฆฌ์ ๋ํ์ ๊ธ์ ํฌ๊ธฐ ๋ฒํผ๋ค์ body ์์์ font-size ์์ฑ์ ๋ณ๊ฒฝํ ์ ์๊ณ , ์ด๋ฐ ์กฐ์ ์ ์๋์ ๋จ์๋ค ๋๋ถ์ ํ์ด์ง์ ๋ค๋ฅธ ์์์ ์ํด ์ ํ๋ฉ๋๋ค.
์ฌ๊ธฐ JavaScript ์ฝ๋๊ฐ ์์ต๋๋ค.
function makeSizer(size) {
return function () {
document.body.style.fontSize = `${size}px`;
};
}
const size12 = makeSizer(12);
const size14 = makeSizer(14);
const size16 = makeSizer(16);
size12, size14, size16์ body ์์์ ๊ธ์ ํฌ๊ธฐ๋ฅผ ๊ฐ๊ฐ 12, 14, 16 ํฝ์
๋ก ๋ฐ๊พธ๋ ํจ์์
๋๋ค. ์ด ํจ์๋ค์ ๋ค์๊ณผ ๊ฐ์ด ๋ฒํผ๋ค์(์ด ๊ฒฝ์ฐ์๋ ํ์ดํผ๋งํฌ) ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
document.getElementById("size-12").onclick = size12;
document.getElementById("size-14").onclick = size14;
document.getElementById("size-16").onclick = size16;
<a href="#" id="size-12">12</a>
<a href="#" id="size-14">14</a>
<a href="#" id="size-16">16</a>
JSFiddle์ ์คํํด๋ณด์ธ์.
ํด๋ก์ ๋ฅผ ์ด์ฉํด์ ๋น๊ณต๊ฐ ๋ฉ์๋ (private method) ํ๋ด๋ด๊ธฐ
์๋ฐ์ ๊ฐ์ ๋ช๋ช ์ธ์ด๋ค์ ๋ฉ์๋๋ฅผ ๋น๊ณต๊ฐ๋ก ์ ์ธํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ ๊ฐ์ ํด๋์ค ๋ด๋ถ์ ๋ค๋ฅธ ๋ฉ์๋์์๋ง ๊ทธ ๋ฉ์๋๋ค์ ํธ์ถํ ์ ์๋ค๋ ์๋ฏธ์ ๋๋ค.
classes ์ด์ ์ JavaScript์๋ ๋น๊ณต๊ฐ ๋ฉ์๋๋ฅผ ์ ์ธํ๋ ๊ธฐ๋ณธ ๋ฐฉ๋ฒ์ด ์์์ง๋ง, ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ฌ ๋น๊ณต๊ฐ ๋ฉ์๋๋ฅผ ํ๋ด๋ผ ์ ์๋ค๋ ๊ฒ์ด ๊ฐ๋ฅํ์ต๋๋ค. ๋น๊ณต๊ฐ ๋ฉ์๋๋ ์ฝ๋์ ๋ํ ์ ๊ทผ์ ์ ํํ๋ ๋ฐ๋ง ์ ์ฉํ ๊ฒ์ด ์๋๋๋ค. ๋ํ ์ ์ญ ์ด๋ฆ ๊ณต๊ฐ์ ๊ด๋ฆฌํ๋ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค.
์๋ ์ฝ๋๋ ๋น๊ณต๊ฐ ํจ์์ ๋ณ์์ ์ ๊ทผํ๋ ํผ๋ธ๋ฆญ ํจ์๋ฅผ ์ ์ํ๊ธฐ ์ํด ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. ์ด๋ ๊ฒ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ชจ๋ ๋์์ธ ํจํด์ ๋ฐ๋ฅธ๋ค๊ณ ํฉ๋๋ค.
const counter = (function () {
let privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment() {
changeBy(1);
},
decrement() {
changeBy(-1);
},
value() {
return privateCounter;
},
};
})();
console.log(counter.value()); // 0.
counter.increment();
counter.increment();
console.log(counter.value()); // 2.
counter.decrement();
console.log(counter.value()); // 1.
์ด์ ์์ ์์, ๊ฐ ํด๋ก์ ๋ค์ด ๊ณ ์ ํ ์ดํ์ ํ๊ฒฝ์ ๊ฐ์ก์ง๋ง, ์ฌ๊ธฐ์ ์ฐ๋ฆฌ๋ counter.increment, counter.decrement, counter.value ์ธ ํจ์์ ์ํด ๊ณต์ ๋๋ ํ๋์ ์ดํ์ ํ๊ฒฝ์ ๋ง๋ค์ด ์ค๋๋ค.
๊ณต์ ๋๋ ์ดํ์ ํ๊ฒฝ์ ์คํ๋๋ ์ต๋ช
ํจ์ ์์์ ๋ง๋ค์ด์ง๋๋ค. ์ด ์ต๋ช
ํจ์๋ ์ ์๋๋ ์ฆ์ ์คํ๋ฉ๋๋ค(IIFE๋ก ์๋ ค์ ธ ์์ต๋๋ค). ์ด ์ดํ์ ํ๊ฒฝ์ ๋ ๊ฐ์ ๋น๊ณต๊ฐ ํญ๋ชฉ์ ํฌํจํฉ๋๋ค. ํ๋๋ privateCounter๋ผ๋ ๋ณ์์ด๊ณ , ๋๋จธ์ง ํ๋๋ changeBy๋ผ๋ ํจ์์
๋๋ค. ๋ ๋ค ์ต๋ช
ํจ์ ์ธ๋ถ์์ ์ ๊ทผ๋ ์ ์๋ ๋น๊ณต๊ฐ ํญ๋ชฉ์
๋๋ค. ๋์ ์ ์ต๋ช
๋ํผ์์ ๋ฐํ๋ ์ธ ๊ฐ์ ๊ณต๊ฐ ํจ์๋ฅผ ํตํด์๋ง ์ ๊ทผํ ์ ์์ต๋๋ค.
์์ ์ธ ๊ฐ์ง ๊ณต๊ฐ ํจ์๋ ๊ฐ์ ํ๊ฒฝ์ ๊ณต์ ํ๋ ํด๋ก์ ์
๋๋ค. JavaScript์ ์ดํ์ ์ ํจ ๋ฒ์ ๋๋ถ์, ์ธ ํจ์ ๊ฐ๊ฐ privateCounter ๋ณ์์ changeBy ํจ์์ ์ ๊ทผํ ์ ์์ต๋๋ค.
const makeCounter = function () {
let privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment() {
changeBy(1);
},
decrement() {
changeBy(-1);
},
value() {
return privateCounter;
},
};
};
const counter1 = makeCounter();
const counter2 = makeCounter();
console.log(counter1.value()); // 0.
counter1.increment();
counter1.increment();
console.log(counter1.value()); // 2.
counter1.decrement();
console.log(counter1.value()); // 1.
console.log(counter2.value()); // 0.
๋ ์นด์ดํฐ๊ฐ ์๋ก ๋
๋ฆฝ์ฑ์ ์ ์งํ๋ ๋ฐฉ๋ฒ์ ์ฃผ๋ชฉํ์ธ์. ๊ฐ ํด๋ก์ ๋ ์์ฒด ํด๋ก์ ๋ฅผ ํตํด privateCounter ๋ณ์์ ๋ค๋ฅธ ๋ฒ์ ์ ์ฐธ์กฐํฉ๋๋ค. ์นด์ดํฐ ์ค ํ๋๊ฐ ํธ์ถ๋ ๋๋ง๋ค, ์ด ๋ณ์์ ๊ฐ์ ๋ณ๊ฒฝํ์ฌ ์ดํ ํ๊ฒฝ์ด ๋ณ๊ฒฝ๋ฉ๋๋ค. ํ๋์ ํด๋ก์ ์์ ๋ณ์ ๊ฐ์ ๋ณ๊ฒฝํด๋ ๋ค๋ฅธ ํด๋ก์ ์ ๊ฐ์๋ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
์ฐธ๊ณ : ์ด๋ฐ ๋ฐฉ์์ผ๋ก ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์ ๋ณด ์๋๊ณผ ์บก์ํ ๊ฐ์ ์ด์ ๋ค์ ์ป์ ์ ์์ต๋๋ค.
ํด๋ก์ ์ค์ฝํ ์ฒด์ธ
๋ชจ๋ ํด๋ก์ ์๋ ์ธ๊ฐ์ง ์ค์ฝํ(๋ฒ์)๊ฐ ์์ต๋๋ค:
- ์ง์ญ ๋ฒ์ (Local Scope, Own scope)
- ํฌํจํ๊ณ ์๋ ๋ฒ์ (๋ธ๋ก, ํจ์ ๋๋ ๋ชจ๋ ๋ฒ์์ผ ์ ์์)
- ์ ์ญ ๋ฒ์ (Global Scope)
์ผ๋ฐ์ ์ผ๋ก ํ๋ ์ค์๋ ์ธ๋ถ ํจ์ ์์ฒด๊ฐ ์ค์ฒฉ๋ ํจ์์ธ ๊ฒฝ์ฐ, ์ธ๋ถ ํจ์์ ๋ฒ์์ ๋ํ ์ ๊ทผ์ ์ธ๋ถ ํจ์์ ๋๋ฌ์ธ๊ณ ์๋ ๋ฒ์๊ฐ ํฌํจ๋๋ค๋ ์ฌ์ค์ ๊นจ๋ซ์ง ๋ชปํ๋ ๊ฒ์ ๋๋ค. ์ฆ, ํจ๊ณผ์ ์ผ๋ก ํจ์ ๋ฒ์ ์ฒด์ธ์ ์์ฑํฉ๋๋ค. ์๋ ์์ ๋ฅผ ํ์ธํด๋ณด์ธ์.
// ์ ์ญ ๋ฒ์ (global scope)
const e = 10;
function sum(a) {
return function (b) {
return function (c) {
// ์ธ๋ถ ํจ์ ๋ฒ์ (outer functions scope)
return function (d) {
// ์ง์ญ ๋ฒ์ (local scope)
return a + b + c + d + e;
};
};
};
}
console.log(sum(1)(2)(3)(4)); // 20
์ต๋ช ํจ์ ์์ด ์์ฑํ ์๋ ์์ต๋๋ค.
// ์ ์ญ ๋ฒ์ (global scope)
const e = 10;
function sum(a) {
return function sum2(b) {
return function sum3(c) {
// ์ธ๋ถ ํจ์ ๋ฒ์ (outer functions scope)
return function sum4(d) {
// ์ง์ญ ๋ฒ์ (local scope)
return a + b + c + d + e;
};
};
};
}
const sum2 = sum(1);
const sum3 = sum2(2);
const sum4 = sum3(3);
const result = sum4(4);
console.log(result); // 20
์์ ์์ ๋ฅผ ๋ณด๋ฉด, ์ผ๋ จ์ ์ค์ฒฉ๋ ํจ์๋ค์ ํ์ธํ ์ ์์ต๋๋ค. ์ด ํจ์๋ค์ ์ ๋ถ ์ธ๋ถ ํจ์์ ๋ฒ์์ ์ ๊ทผํ ์ ์์ต๋๋ค. ์ด ๋ฌธ๋งฅ์์๋ ํด๋ก์ ๊ฐ ์ ์ธ๋ "๋ชจ๋ " ์ธ๋ถ ํจ์์ ์ค์ฝํ์ ์ ๊ทผํ๋ค๊ณ ๋งํ ์ ์์ต๋๋ค.
ํด๋ก์ ๋ ๋ธ๋ก ๋ฒ์์ ๋ชจ๋ ๋ฒ์์์๋ ๋ณ์๋ฅผ ์บก์ฒํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์์ ๋ธ๋ก ๋ฒ์ ๋ณ์ y์ ๋ํ ํด๋ก์ ๋ฅผ ์์ฑํฉ๋๋ค.
function outer() {
let getY;
{
const y = 6;
getY = () => y;
}
console.log(typeof y); // undefined
console.log(getY()); // 6
}
outer();
๋ชจ๋์ ๋ํ ํด๋ก์ ๋ ๋์ฑ ํฅ๋ฏธ๋กญ์ต๋๋ค.
// myModule.js
let x = 5;
export const getX = () => x;
export const setX = (val) => {
x = val;
};
์ฌ๊ธฐ์์, ๋ชจ๋์ ๋ชจ๋ ๋ฒ์ ๋ณ์ x๋ฅผ ๋ซ๋ ํ ์์ getter-setter ํจ์๋ฅผ ๋ด๋ณด๋
๋๋ค. x๋ ๋ค๋ฅธ ๋ชจ๋์์ ์ง์ ์ ๊ทผํ ์ ์๋ ๊ฒฝ์ฐ์๋, ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๊ณ ์ธ ์ ์์ต๋๋ค.
import { getX, setX } from "./myModule.js";
console.log(getX()); // 5
setX(6);
console.log(getX()); // 6
ํด๋ก์ ๋ ์๋ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด, ๊ฐ์ ธ์จ ๊ฐ๋ ๊ทธ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋๊ธฐ ๋๋ฌธ์ "live bindings"๋ก ๊ฐ์ฃผ๋๋ ๊ฐ์ ธ์จ ๊ฐ์ ๋ซ์ ์ ์์ต๋๋ค.
// myModule.js
export let x = 1;
export const setX = (val) => {
x = val;
};
// closureCreator.js
import { x } from "./myModule.js";
export const getX = () => x;
// ๊ฐ์ ธ์จ live binding์ ๋ซ์ต๋๋ค.
import { getX } from "./closureCreator.js";
import { setX } from "./myModule.js";
console.log(getX()); // 1
setX(2);
console.log(getX()); // 2
๋ฃจํ์์ ํด๋ก์ ์์ฑํ๊ธฐ: ์ผ๋ฐ์ ์ธ ์ค์
let ํค์๋๊ฐ ๋์
๋๊ธฐ ์ ์๋ ํด๋ก์ ์ ๊ด๋ จ๋ ์ผ๋ฐ์ ์ธ ๋ฌธ์ ๋ ๋ฃจํ ์์์ ํด๋ก์ ๊ฐ ์์ฑ๋์์ ๋ ๋ฐ์ํ์ต๋๋ค. ๋ค์ ์์ ๋ฅผ ๋ด
์๋ค.
<p id="help">Helpful notes will appear here</p>
<p>E-mail: <input type="text" id="email" name="email" /></p>
<p>Name: <input type="text" id="name" name="name" /></p>
<p>Age: <input type="text" id="age" name="age" /></p>
function showHelp(help) {
document.getElementById("help").textContent = help;
}
function setupHelp() {
var helpText = [
{ id: "email", help: "Your e-mail address" },
{ id: "name", help: "Your full name" },
{ id: "age", help: "Your age (you must be over 16)" },
];
for (var i = 0; i < helpText.length; i++) {
// ๋ฒ์ธ์ ์ด ์ค์์ `var`๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
var item = helpText[i];
document.getElementById(item.id).onfocus = function () {
showHelp(item.help);
};
}
}
setupHelp();
JSFiddle ์ฝ๋๋ฅผ ์คํํด๋ณด์ธ์.
helpText ๋ฐฐ์ด์ ์ธ ๊ฐ์ ๋์๋ง ํํธ๋ฅผ ์ ์ํ๋ฉฐ, ๊ฐ ๋์๋ง์ ๋ฌธ์์ ์
๋ ฅ ํ๋์ ID์ ์ฐ๊ด๋ฉ๋๋ค. ๋ฐ๋ณต๋ฌธ์ ๋๋ฉด์ ๊ฐ ์
๋ ฅ ํ๋ ID์ ํด๋นํ๋ ์๋ฆฌ๋จผํธ์ onfocus ์ด๋ฒคํธ์ ๊ด๋ จ๋ ๋์๋ง์ ๋ณด์ฌ์ฃผ๋ ๋ฉ์๋์ ์ฐ๊ฒฐํฉ๋๋ค.
์ด ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ ๋๋ก ๋์ํ์ง ์๋ ๊ฒ์ ์๊ฒ ๋ฉ๋๋ค. ์ด๋ค ํ๋์ ํฌ์ปค์ค๋ฅผ ์ฃผ๋๋ผ๋ ๋์ด์ ๊ดํ ๋์๋ง์ด ํ์๋ฉ๋๋ค.
๊ทธ ์ด์ ๋ onfocus ์ด๋ฒคํธ์ ์ฐ๊ฒฐ๋ ํจ์๊ฐ ํด๋ก์ ์ด๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด ํด๋ก์ ๋ ํจ์ ์ ์์ setupHelp ํจ์ ๋ฒ์์์ ์บก์ฒ๋ ํ๊ฒฝ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ๋ฐ๋ณต๋ฌธ์์ ์ธ ๊ฐ์ ํด๋ก์ ๊ฐ ๋ง๋ค์ด์ก์ง๋ง, ๊ฐ ํด๋ก์ ๋ ๊ฐ์ด ๋ณํ๋ ๋ณ์๊ฐ (item) ์๋ ๊ฐ์ ๋จ์ผ ์ดํ์ ํ๊ฒฝ์ ๊ณต์ ํฉ๋๋ค. ์ด๋ ๋ณ์ item์ด var๋ก ์ ์ธ๋์ด ํธ์ด์คํ
(hoisting)์ผ๋ก ์ธํด ํจ์ ๋ฒ์๊ฐ ์๊ธฐ ๋๋ฌธ์
๋๋ค. item.help์ ๊ฐ์ onfocus ์ฝ๋ฐฑ์ด ์คํ๋ ๋ ๊ฒฐ์ ๋ฉ๋๋ค. ๋ฐ๋ณต๋ฌธ์ ๊ทธ ์๊ฐ๊น์ง ์ด๋ฏธ ๊ทธ ๊ณผ์ ์ ์คํํ๊ธฐ ๋๋ฌธ์, item ๋ณ์ ๊ฐ์ฒด(์ธ ๊ฐ์ ํด๋ก์ ๋ชจ๋์์ ๊ณต์ ํ๋)๋ helpText ๋ชฉ๋ก์ ๋ง์ง๋ง ํญ๋ชฉ์ ๊ฐ๋ฆฌํค๊ณ ์์ต๋๋ค.
์ด ๊ฒฝ์ฐ ํ ๊ฐ์ง ํด๊ฒฐ์ฑ ์ ๋ ๋ง์ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ํนํ ์์์ ์ค๋ช ํ ํจ์ ํฉํ ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
function showHelp(help) {
document.getElementById("help").innerHTML = help;
}
function makeHelpCallback(help) {
return function () {
showHelp(help);
};
}
function setupHelp() {
var helpText = [
{ id: "email", help: "Your e-mail address" },
{ id: "name", help: "Your full name" },
{ id: "age", help: "Your age (you must be over 16)" },
];
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = makeHelpCallback(item.help);
}
}
setupHelp();
์ด JSFiddle ๋งํฌ๋ฅผ ์คํํด๋ณด์ธ์.
์ด๊ฒ์ ์์๋๋ก ๋์ํฉ๋๋ค. ๋ชจ๋ ๋จ์ผ ์ดํ ํ๊ฒฝ์ ๊ณต์ ํ๋ ์ฝ๋ฐฑ ๋์ ์, makeHelpCallback ํจ์๋ ๊ฐ๊ฐ์ ์ฝ๋ฐฑ์ "์๋ก์ด ์ดํ์ ํ๊ฒฝ"์ ์์ฑํฉ๋๋ค. ์ฌ๊ธฐ์, help๋ helpText ๋ฐฐ์ด์ ํด๋น ๋ฌธ์์ด์ ๋ํ๋
๋๋ค.
์ต๋ช ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
function showHelp(help) {
document.getElementById("help").innerHTML = help;
}
function setupHelp() {
var helpText = [
{ id: "email", help: "Your e-mail address" },
{ id: "name", help: "Your full name" },
{ id: "age", help: "Your age (you must be over 16)" },
];
for (var i = 0; i < helpText.length; i++) {
(function () {
var item = helpText[i];
document.getElementById(item.id).onfocus = function () {
showHelp(item.help);
};
})(); // ํญ๋ชฉ์ ํ์ฌ ๊ฐ์ด ํฌํจ๋ ์ฆ๊ฐ์ ์ธ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ถ๊ฐ(๋ฐ๋ณต๋ ๋๊น์ง ๋ณด์กด๋ฉ๋๋ค).
}
}
setupHelp();
ํด๋ก์ ๋ฅผ ๋ ์ด์ ์ฌ์ฉํ์ง ์์ผ๋ ค๋ฉด, let ๋๋ const ํค์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
function showHelp(help) {
document.getElementById("help").textContent = help;
}
function setupHelp() {
const helpText = [
{ id: "email", help: "Your email address" },
{ id: "name", help: "Your full name" },
{ id: "age", help: "Your age (you must be over 16)" },
];
for (let i = 0; i < helpText.length; i++) {
const item = helpText[i];
document.getElementById(item.id).onfocus = () => {
showHelp(item.help);
};
}
}
setupHelp();
์์ ๊ฒฝ์ฐ var ๋์ const์ ์ฌ์ฉํ์ฌ ๋ชจ๋ ํด๋ก์ ๊ฐ ๋ธ๋ก ๋ฒ์ ๋ณ์๋ฅผ ๋ฐ์ธ๋ฉํ ๊ฒ์ด๋ฏ๋ก ์ถ๊ฐ์ ์ธ ํด๋ก์ ๊ฐ ํ์ํ์ง ์์ต๋๋ค.
๋ ๋ค๋ฅธ ๋์์ ๋ค์๊ณผ ๊ฐ์ด forEach()๋ฅผ ์ฌ์ฉํ์ฌ helpText ๋ฐฐ์ด์ ๋ฐ๋ณตํ๊ณ ๊ฐ <input>์ ๋ฆฌ์ค๋๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์
๋๋ค.
function showHelp(help) {
document.getElementById("help").textContent = help;
}
function setupHelp() {
var helpText = [
{ id: "email", help: "Your e-mail address" },
{ id: "name", help: "Your full name" },
{ id: "age", help: "Your age (you must be over 16)" },
];
helpText.forEach(function (text) {
document.getElementById(text.id).onfocus = function () {
showHelp(text.help);
};
});
}
setupHelp();
์ฑ๋ฅ ๊ด๋ จ ๊ณ ๋ ค ์ฌํญ
์์์ ์ธ๊ธํ๋ฏ์ด, ๊ฐ ํจ์ ์ธ์คํด์ค๋ ์์ฒด ๋ฒ์์ ํด๋ก์ ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ํน์ ์์ ์ ํด๋ก์ ๊ฐ ํ์ํ์ง ์๋๋ฐ ๋ค๋ฅธ ํจ์ ๋ด์์ ํจ์๋ฅผ ๋ถํ์ํ๊ฒ ์์ฑํ๋ ๊ฒ์ ์ฒ๋ฆฌ ์๋์ ๋ฉ๋ชจ๋ฆฌ ์๋น ์ธก๋ฉด์์ ์คํฌ๋ฆฝํธ ์ฑ๋ฅ์ ๋ถ์ ์ ์ธ ์ํฅ์ ๋ฏธ์น๊ธฐ ๋๋ฌธ์, ํ๋ช ํ์ง ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ์๋ก์ด ๊ฐ์ฒด/ํด๋์ค๋ฅผ ์์ฑํ ๋, ๋ฉ์๋๋ ์ผ๋ฐ์ ์ผ๋ก ๊ฐ์ฒด ์์ฑ์์ ์ ์๋๊ธฐ๋ณด๋ค๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ ์ฐ๊ฒฐ๋์ด์ผ ํฉ๋๋ค. ๊ทธ ์ด์ ๋ ์์ฑ์๊ฐ ํธ์ถ๋ ๋๋ง๋ค ๋ฉ์๋๊ฐ ๋ค์ ํ ๋น๋๊ธฐ ๋๋ฌธ์ ๋๋ค(์ฆ, ๋ชจ๋ ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋๋ง๋ค).
๋ค์ ์๋ฅผ ์๊ฐํด๋ณด์ธ์.
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
this.getName = function () {
return this.name;
};
this.getMessage = function () {
return this.message;
};
}
์์ ์ฝ๋๋ ํน์ ์ธ์คํด์ค์์ ํด๋ก์ ์ ์ด์ ์ ํ์ฉํ์ง ์์์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ง ์๋๋ก ๋ค์ ์ธ ์ ์์ต๋๋ค.
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype = {
getName() {
return this.name;
},
getMessage() {
return this.message;
},
};
๊ทธ๋ฌ๋, ํ๋กํ ํ์ ์ ๋ค์ ์ ์ํ๋ ๊ฒ์ ๊ถ์ฅ๋์ง ์์ผ๋ฏ๋ก, ๊ธฐ์กด ํ๋กํ ํ์ ์ ์ถ๊ฐํ๋ ๋ค์ ์์ ๊ฐ ๋ ์ข์ต๋๋ค.
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype.getName = function () {
return this.name;
};
MyObject.prototype.getMessage = function () {
return this.message;
};
์์ ๋ ๊ฐ์ง ์์ ์์, ์์๋ ํ๋กํ ํ์ ์ ๋ชจ๋ ๊ฐ์ฒด์์ ๊ณต์ ๋ ์ ์์ผ๋ฉฐ ๋ฉ์๋ ์ ์๋ ๊ฐ์ฒด ์์ฑ์๋ง๋ค ๋ฐ์ํ ํ์๊ฐ ์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ์์ ๋ฐ ํ๋กํ ํ์ ์ฒด์ธ์ ์ฐธ๊ณ ํ์ธ์.