[마스터 개념] 9 | 클로져, this
1 variable 변수
2 operator 연산자
3 function 함수
4 object 객체
5 class 클래스
7 built-in 빌트인 객체
8 array 배열
9 iterator 이터러블
10 map
11 more-operators 유용한 연산자들
12 module 모듈
13 promise 프로미스
14 scope 스코프
15 prototype 프로토타입
16> closure 클로져
17> this
15 closure 클로져
클로져
내부 함수가 외부 함수의 변수를 기억하게 한다.
즉, 외부 함수가 호출되어 실행된 후에도 내부 함수는 외부 함수의 변수에 접근할 수 있다.
외부에서는 그 변수를 직접 접근할 수 없도록 만들어 준다.
> 변수를 보호, 상태의 캡슐화
function outer() {
const x = 0;
function inner() {
console.log(`inside inner : ${x}`);
}
return inner;
}
const func1 = outer();
func1(); // inside inner : 0
outer( ) 는 inner 의 참조값을 반환한다. 근데 func1 에 inner 의 참조값이 할당됐으므로 inner( ) 가 할당된다.
이때, 클로져에 의해 함수뿐만(inner( )) 아니라 변수가 들어있는 렉시컬 환경도(x = 0) 함께 묶여서 반환되기 때문에 inner 의 x 값이 0으로 나타날 수 있다.
function makeCounter() {
let count = 0;
function increase() {
count++;
console.log(count);
}
return increase;
}
const increase = makeCounter();
increase(); // 1
increase(); // 2
increase(); // 3
// ----------------------------
class Counter {
#count = 0;
increase() {
this.#count++;
console.log(this.#count);
}
}
const counter = new Counter();
counter.increase(); // 1
이때, increase( ) 를 통해서만 count 를 조작할 수 있다.
따라서 클로져는 내부 정보를 은닉하고, 공개 함수(public, 외부) 를 통한 데이터 조작을 위해 쓰인다. 클래스 private 필드나 메서드를 사용하는 효과와 동일하다.
// let과 var의 차이점!
function loop() {
const array = [];
for (let i = 0; i < 5; i++) {
array.push(function () {
console.log(i);
});
}
return array;
}
const array = loop();
array.forEach((func) => func());
// 0 1 2 3 4
loop( ) 함수는 array 에 i 를 출력하는 함수들이 들어있는 배열의 참조값을 반환한다. 이때, let 은 블록스코프 이기 때문에, for 문의 let i = 0 의 값도 클로져에 의해 i 를 출력하는 함수와 묶여서 반환된다.
따라서 각각의 함수들은 클로져에 의해 외부의 블록스코프에 함께 i 의 정보를 가진다.
// let과 var의 차이점!
function loop() {
const array = [];
for (var i = 0; i < 5; i++) {
array.push(function () {
console.log(i);
});
}
return array;
}
const array = loop();
array.forEach((func) => func());
// 5 5 5 5 5
var 는 함수스코프이기 때문에, 최종적으로 i = 5인 하나의 변수로만 남아있다.
this
자바스크립트에서는 호출하는 사람에 의해 동적으로 결정된다.
function Cat(name) {
this.name = name;
this.printName = function () {
console.log(`고양이 이름 : ${this.name}`);
};
}
function Dog(name) {
this.name = name;
this.printName = function () {
console.log(`강아지 이름 : ${this.name}`);
};
}
const cat = new Cat("냐옹");
const dog = new Dog("멍멍");
cat.printName(); // 고양이 이름 : 냐옹
dog.printName(); // 강아지 이름 : 멍멍
dog.printName = cat.printName;
dog.printName(); // 고양이 이름 : 멍멍
cat.printName(); // 고양이 이름 : 냐옹
Object.함수( ) 를 하면 해당 Object 가 this 로 바인딩된다.
정적으로 this 를 바인딩하는 방법
1. bind 함수를 이용하여 수동으로 바인딩 ( this.함수 = this.함수.bind(this) )
2. arrow 함수를 이용 : arrow 함수는 렉시컬 환경에서의 this를 기억하고, arrow 함수 밖에서 제일 근접한 스코프의 this 를 가리킴 ( this.함수 = ( ) => { 함수내용 } )
arrow 함수
화살표 함수
1. 문법이 깔끔
2. 생성자 함수로 사용이 불가능 (무거운 프로토타입 만들지 않음)
3. 함수 안에 무거운 arguments 객체를 가지고 있지 않음
- arguments 출력하면, arrow 함수 외부의 argumetns 를 참조만 함
4. this에 대한 바인딩이 정적으로 결정
- 함수에서 제일 근접한 상위 스코프의 this에 정적으로 바인딩 됨
'💠프로그래밍 언어 > JavaScript' 카테고리의 다른 글
[심화] substr / substring / slice 의 차이점이 뭘까? (0) | 2024.07.08 |
---|---|
[심화] 아스키코드 / replace / break, continue / localeCompare / charAt(i) / 진수 변환, 2차원배열 (0) | 2023.10.24 |
[마스터 개념] 8 | 스코프, 프로토타입 (0) | 2022.11.15 |
[마스터 개념] 7 | 프로미스 (0) | 2022.11.11 |
[마스터 개념] 6 | 모듈 (0) | 2022.11.07 |