Chapter 7: Using Closures - hochan222/Everything-in-JavaScript GitHub Wiki
See the Closure
ν΄λ‘μ λ ν¨μμλ§ μλ€. κ°μ²΄μ ν΄λμ€λ ν΄λ‘μ λ₯Ό κ°μ μ μμ΅λλ€.
Pointed Closure
=> νμ΄νν¨μλ λ²μλ₯Ό μμ±ν©λλ€.
var student = students.find(
student =>
// function scope: ORANGE(4)
student.id == studentID
);
μ΄λ κ² => νμ΄ν ν¨μ λ΄μμλ studentID λ₯Ό μ°Έμ‘°ν μ μμΌλ―λ‘ ν΄λ‘μ κ° μ μ§ λ μ μμμ μμμΌν©λλ€.
Adding Up Closures
ν΄λ‘μ λ μ»΄νμΌ νμμ μ²λ¦¬λλ μ΄ν λ²μλ₯Ό κΈ°λ°μΌλ‘νμ§λ§ ν΄λ‘μ λ ν¨μ μΈμ€ν΄μ€μ λ°νμ νΉμ±μΌλ‘ κ΄μ°°λ©λλ€.
Live Link, Not a Snapshot
ν΄λ‘μ λ μ€μ λ‘ μ 체 λ³μ μ체μ λν μ‘μΈμ€λ₯Ό μ μ§νλ λΌμ΄λΈ λ§ν¬μ λλ€. λ«ν λ³μλ μ λ°μ΄νΈ(μ¬ ν λΉ) ν μ μμ΅λλ€.
ν΄λ‘μ λ λ³μκ° μλ κ°μ μ§ν₯ν©λλ€.
var keeps = [];
for (var i = 0; i < 3; i++) {
keeps[i] = function keepI(){
// closure over `i`
return i;
};
}
keeps[0](); // 3 -- WHY!?
keeps[1](); // 3
keeps[2](); // 3
μ΄ μΈκ°μ ν΄λ‘μ λ κ°κ° λ€λ₯Έ ν¨μλ₯Ό κ°μ§λ§ κ°μ λ³μλ₯Ό 곡μ ν©λλ€.
ν¨μλ§λ€ λ€λ₯Έ λ³μλ₯Ό λ§λ€λ©΄ μμ λμμ΄ λ©λλ€.
var keeps = [];
for (var i = 0; i < 3; i++) {
// new `j` created each iteration, which gets
// a copy of the value of `i` at this moment
let j = i;
// the `i` here isn't being closed over, so
// it's fine to immediately use its current
// value in each loop iteration
keeps[i] = function keepEachJ(){
// close over `j`, not `i`!
return j;
};
}
keeps[0](); // 0
keeps[1](); // 1
keeps[2](); // 2
What If I Canβt See It?
function lookupStudent(studentID) {
return function nobody(){
var msg = "Nobody's here yet.";
console.log(msg);
};
}
var student = lookupStudent(112);
student();
// Nobody's here yet.
GCλ studentIDκ° λμ΄μ νΈμΆλμ§ μμΌλ―λ‘ μ 리νλ € ν κ²μ λλ€.
function greetStudent(studentName) {
return function greeting(){
console.log(
`Hello, ${ studentName }!`
);
};
}
greetStudent("Kyle");
μ¬κΈ°μ λ°ν λ ν¨μλ λ²λ €μ§λλ€. λ°λΌμ κΈ°μ μ μΌλ‘ JS μμ§μ΄ μ κΉ λμ ν΄λ‘μ λ₯Ό μμ±νλλΌλ μ΄ νλ‘κ·Έλ¨μμλ μλ―Έμλ λ°©μμΌλ‘ κ΄μ°°λμ§ μμμ΅λλ€.
λ°λΌμ μ΄ μ μ μλ λͺ¨λ μμ λ ν΄λ‘μ κ° μλλλ€.
Observable Definition
ν΄λ‘μ λ ν¨μμμ μ κ·Όν μ μλ λμμ λ°κΉ₯ λ²μμμ λ³μλ₯Ό μ¬μ©νλ κ²μ λλ€.
- ν¨μμ ν¬ν¨λμ΄μΌ ν©λλ€.
- λ°μ Scopeμμ μ μ΄λ νλμ λ³μκ° μ°Έμ‘°λμ΄μΌ ν©λλ€.
- λ²μ λ° μ²΄μΈμμ λ€λ₯Έ λΆκΈ°μμ νΈμΆλμ΄μΌ ν©λλ€.
The Closure Lifecycle and Garbage Collection (GC)
ν΄λ‘μ λ λ³Έμ§μ μΌλ‘ ν¨μ μΈμ€ν΄μ€μ μ°κ²°λμ΄ μκΈ° λλ¬Έμ λ³μμ λν ν΄λ‘μ λ ν΄λΉ ν¨μμ λν μ°Έμ‘°κ° μλ ν μ§μλ©λλ€. μ΅μ’ ν¨μ μ°Έμ‘°κ° μμ λλ©΄ ν΄λΉ λ³μμ λν λ§μ§λ§ ν΄λ‘μ κ° μ¬λΌμ§κ³ λ³μ μμ²΄κ° GCλ©λλ€.
ν΄λ‘μ λ μκ°μ΄ μ§λ¨μ λ°λΌ λ©λͺ¨λ¦¬ μ¬μ©λμ΄ κΈμ¦νλ λ³μμ GCλ₯Ό μκΈ°μΉ μκ² λ°©μ§ ν μ μμ΅λλ€. κ·Έλ κΈ° λλ¬Έμ λ μ΄μ νμνμ§ μμ λ ν¨μ μ°Έμ‘° (λ° κ·Έμ λ°λ₯Έ ν΄λ‘μ )λ₯Ό λ²λ¦¬λ κ²μ΄ μ€μν©λλ€.
Per Variable or Per Scope?
function storeStudentInfo(id,name,grade) {
return function getInfo(whichValue){
// warning:
// using `eval(..)` is a bad idea!
var val = eval(whichValue);
return val;
};
}
var info = storeStudentInfo(73,"Suzy",87);
info("name");
// Suzy
info("grade");
// 87
κ°λ μ μΌλ‘ ν΄λ‘μ λ λ²μκ° μλ λ³μ λ³λ‘ μ΄λ£¨μ΄μ§λλ€. Ajax μ½λ°±, μ΄λ²€νΈ νΈλ€λ¬ λ° κΈ°ν λͺ¨λ ννμ ν¨μ ν΄λ‘μ λ μΌλ°μ μΌλ‘ λͺ μ μ μΌλ‘ μ°Έμ‘°νλ νλͺ© λ§ λ«λ κ²μΌλ‘ κ°μ£Όλ©λλ€.
λ§μ μ΅μ JS μμ§μ λͺ μμ μΌλ‘ μ°Έμ‘°λμ§ μμ ν΄λ‘μ λ²μμμ λͺ¨λ λ³μλ₯Ό μ κ±°νλ μ΅μ νλ₯Ό μ μ©ν©λλ€. κ·Έλ¬λ eval(..)μμ λ³Ό μ μλ―μ΄ μ΄λ¬ν μ΅μ νλ₯Ό μ μ© ν μμλ μν©μ΄ μμΌλ©° ν΄λ‘μ λ²μμλ λͺ¨λ μλ λ³μκ° κ³μ ν¬ν¨λ©λλ€.
λͺ λ μ κΉμ§ λ§ν΄λ λ§μ JS μμ§μ΄μ΄ μ΅μ νλ₯Ό μ μ©νμ§ μμμ΅λλ€. μΉ μ¬μ΄νΈκ° μ΄λ¬ν λΈλΌμ°μ , νΉν ꡬν λλ μ κ°ν κΈ°κΈ°μμ κ³μ μ€νλ μ μμ΅λλ€. μ¦, μ΄λ²€νΈ νΈλ€λ¬μ κ°μ μλͺ μ΄ κΈ΄ ν΄λ‘μ κ° μ°λ¦¬κ° μκ°νλ κ²λ³΄λ€ ν¨μ¬ μ€λ λ©λͺ¨λ¦¬λ₯Ό 보μ ν μ μμ΅λλ€. μ¬μμ΄μλλΌ μ νμ μ΅μ νλΌμ μ°λ¦¬κ° 무λΆλ³νκ² μ¬μ©νλ©΄ μλ©λλ€.
λ°λΌμ μ°λ¦¬λ νμμ λ°λΌμλ λͺ μμ μΌλ‘ μ΄λ° κ²λ€μ GCλ μ΅μ νμ μμ‘΄νμ§ μκ³ μ½λ©ν νμκ° μλ€.
function manageStudentGrades(studentRecords) {
var grades = studentRecords.map(getGrade);
// unset `studentRecords` to prevent unwanted
// memory retention in the closure
studentRecords = null;
return addGrade;
// ..
}
studentRecords = null; λ‘μ¨ ν΄λ‘μ μμ μμ μ€λ€.
μμ½: ν΄λ‘μ λ₯Ό ν΅ν΄ λ΄λΆ λ³μλ₯Ό μ°Έμ‘°νλ λμμλ λ΄λΆ λ³μκ° μ°¨μ§νλ λ©λͺ¨λ¦¬λ₯Ό GCκ° νμνμ§ μλλ€. λ°λΌμ ν΄λ‘μ μ¬μ©μ΄ λλλ©΄ μ°Έμ‘°λ₯Ό μ κ±°νλ κ²μ΄ μ’λ€.