728x90
반응형
- 주변 상태에 대한 참조와 함께 묶인 함수의 조합, 내부 함수에서 외부 함수의 범위에 대한 접근 제공
js에서 클로저는 함수가 생성될 때마다 생성됨
- 오직 하나의 메소드를 가지고 있는 객체를 일반적으로 사용하는 모든 곳에 클로저를 사용할 수 있음
어휘적 범위 지정 (Lexical scopeing)
function init() {
var name = "Mozilla"; // name은 init에 의해 생성된 지역 변수
function displayName() {
// displayName() 은 내부 함수이며, 클로저
console.log(name); // 부모 함수에서 선언된 변수를 사용
}
displayName();
}
init();
ex2
function outerFunction() {
let outerVariable = 'I am outside!';
function innerFunction() {
console.log(outerVariable); // outerFunction의 스코프에 있는 outerVariable에 접근
}
return innerFunction;
}
const closureFunction = outerFunction();
closureFunction(); // "I am outside!" 출력
ex3
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
- 당연히 서로 다른 환경을 가짐
클로저를 이용, private method 흉내내기
- 모듈 디자인 패턴,
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.
클로저 스코프 체인
세가지 스코프
- 지역 범위(Local Scope, Own 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
* 위의 함수들은 전부 외부함수의 범위에 접근중임
블록 범위의 변수 캡처
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;
};
import { getX, setX } from "./myModule.js";
console.log(getX()); // 5
setX(6);
console.log(getX()); // 6
루프에서 클로저 생성
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();
이 코드에서 var를 사용해서 원하는 텍스트가 안나오고 맨 마지막 텍스트가 나오는데
var 가 함수형 스코프이기 때문임.
해결책 1
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();
해결2 (항목의 현재 값이 포함된 즉각적인 이벤트 리스너 추가)
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();
해결3 클로저를 사용하지 않고 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();
*함수 스코프 - 변수가 함수 내에서만 유효한 범위를 가짐
function exampleFunction() {
var functionScopedVariable = 'I am a function scoped variable';
if (true) {
var insideBlock = 'I am still function scoped';
console.log(functionScopedVariable); // 접근 가능
}
console.log(insideBlock); // 접근 가능
}
exampleFunction();
console.log(functionScopedVariable); // 오류: 함수 외부에서는 접근 불가
*블록 스코프 - 변수가 블록 내에서만 유효한 범위를 가짐
function exampleFunction() {
let blockScopedVariable = 'I am a block scoped variable';
if (true) {
let insideBlock = 'I am block scoped';
console.log(blockScopedVariable); // 접근 가능
console.log(insideBlock); // 접근 가능
}
console.log(insideBlock); // 오류: 블록 외부에서는 접근 불가
}
exampleFunction();
console.log(blockScopedVariable); // 오류: 함수 외부에서는 접근 불가
예전에 어떤 개발자 오픈카톡에서 누가 블록안에 코드를 넣으라는데 블록이 어딘지 모르겠다길래
블록은 { } 이거다 라고 하니까 사람들이 아니라고.. 다른거 같은데요??? 다른 코드도 보여주실래요??? 요ㅈㄹ..하길래..
할 말을 잃고 조용히 방을 나왔던 기억이 난다..
728x90
반응형
'Language > Java Script' 카테고리의 다른 글
| 여러조건 비교 includes (0) | 2024.09.05 |
|---|---|
| 프로토타입과 클래스 (0) | 2022.06.04 |
| 배열 내장함수 (0) | 2022.06.04 |
| 반복문 for...in (0) | 2022.06.03 |
| reduce (0) | 2022.05.20 |
| spread 와 rest (0) | 2022.05.19 |