📍 오늘배운내용
- 실행컨텍스트 (및 JS의 코드실행순서)와 this 에대해 알아보자
- 클로저라는 개념 모를때는 우리가 사용하고 있었지만 개념으로 공부하니까 어려웠다!
=> 정말 간단하게 말하자면 함수가 종료되면 함수내부의 변수는 사라지지만 외부로 전달하여 사용가능한것을 클로저라고 하자- 일반함수와 화살표함수가 가르키는
this를 알아두기!
자바스크립트 엔진은 코드가 없어도 3가지 변수를 포함해서 실행환경(실행컨텍스트)를 초기화한다.
1.this
- this 포인터의 경우, 글로벌 스코프에서는 window(global)를 가르킨다.
2. 변수들 (Variable Object)
3.Scope chain
- scope는 코드가 현재 실행되는 환경, 맥락을 의미한다.📍 자바스크립트가 실행되면
전역 실행 컨텍스트(Global Exeuction Context)가 만들어지고 함수가 실행될때는함수 실행 컨텍스트(Function Execution Context)가 만들어진다.
📍 함수가 실행되면 함수 스코프에 따라 환경이 만들어지고 this, 변수, 스코프체인이 형성된다. 함수 실행이 끝나면 스코프 체인을 따라 글로벌 환경에 도달한다.
어떤 코드도 없는경우(실행하는 함수) : 예를들어 html/css로만 구성된 웹을 브라우저에 실행할때
console.log(this); //window
this : windowVariable Object) : {}Scope chain : []특정 함수가 존재하고 실행되는 경우
function fac() {
let a = 100;
let b = 200;
function mul (first, second) {
return first * second;
}
return mul(a,b)
}
//fac 함수 실행
fac();
| Executive Context | fac() | mul() |
|---|---|---|
| this | undefined (strict mode - js 실행될때 정해진 mode..) | undefined |
| Variable Object | { a:100, b:200, mul:function{..} } | { first : 100, second : 200} |
| Scope chain | global | fac, global |
mul()은 실행이 끝나면 해당 실행컨텍스트는 모두 삭제되고 fac 스코프로 돌아간다.
fac 실행이 끝나면 원래 모두 삭제되고 실행되는 코드가 없던 상태로 돌아감(global 스코프로 돌아감!)
스택에 쌓이게 된다.call stack)스택의 자료구조 처럼 가장 나중에 실행된 함수의 실행컨텍스트가 가장 먼저 제거된다!
let a =20;
function func() {
let b= 30;
function check(v) {console.log(v)}
function func2() {
let c = 40;
check(a+b+c)//=========== 4
}
func2() //=========== 3
}
func() //============== 2
//====================1
Global : a , console(전역객체이기 때문에), func함수
func 함수 : b, check함수, func2함수 (전역에서 func() 에 의해 실행)
func2 함수 : c (전역 > func() 내에서 func2() 에의해 실행)
check 함수 : v (전역 > func() > func2내에서 check(a+b+c) 에 의해 실행)
call 과 apply 는 기본적인 function 의 객체
bind, apply, call 등으로 this 가 가르키는 것을 조작할 수 있다!bind(p) : this가 p 객체를 가리키도록let o = {
name: "zeeyoon",
f1: () => {
console.log("[f1] this :", this);
},
f2: function () {
console.log("[f2] this :", this);
},
};
o.f1(); // 화살표함수 global
o.f2(); // 일반함수 a
setTimeout(o.f1, 10); //콜백함수 global
setTimeout(o.f2, 20); //콜백함수 global
화살표 함수와 콜백함수로 함수를 실행할때는 기존의 맥락(this)를 전역 컨텍스트의 맥락으로 바꾼다.
- 화살표 함수의 this
- 항상 상위 스코프의 this를 가르킨다.
- 화살표 함수의 this는 정해지면 apply, bind, call 로도 조작할 수 없음
- 일반함수의 this ⇒ 새롭게 생성된 실행 컨텍스트를 가르킴 (함수가 만들어진 환경의 스코프)
- 메소드와 함수는 다르다! (간단하게 점 혹은 대괄호의 여부로 구분하기 > 있다면 메소드)
1. 함수 실행 시에는, 전역(window)객체를 가리킨다.
2. 메소드 실행 시에는 메소드를 소유하고 있는 객체를 가리킨다.
3. 생성자 실행 시에는 새롭게 만들어진 객체를 가리킨다.
const fac = {
method() {
console.log("context : ", this); //fac
let func1 = function () {
console.log("[일반함수 func2] this : " , this);
}
let func2 = () =>
console.log("[화살표함수 func2] this : " , this);
func1(); // global
func2(); // fac 화살표 함수이기때문에 호출된 위치인 method
},
};
fac.method();
func1 이 global을 가르키는 이유는?(⭐️⭐️⭐️⭐️)func1 함수가 실행되면서 새로운 컨텍스트를 생성하는데 바인딩된 컨텍스트가 없으므로 this는 gobal을 가르킨다.method 내의 context: this 가 fac 인 이유는 global 에서 호출했을때 fac.method() 에 의해 global > fac() > method() 의 순서로 새로운 컨텍스트를 생성했기 때문임.let bio = {
name: "zeeyoon",
hello : function() {
console.log("안녕 내이름은 ", this.name);
},
};
bio.hello();
//안녕 내이름은 zeeyoon (hello 의 this는 bio)
//콜백함수 > 전역객체를 바인딩한다
setTimeout(bio.hello, 10);
//안녕 내이름은 undefined (hello의 this는 global)
setTimeout(bio.hello.bind(bio), 20); //안녕 내이름은 zeeyoon
// (hello의this를 global에서 bio 로 바인딩)
외부로 전달하는 방법
일급객체란, 다른 변수처럼 대상을 다룰 수 있는것 var f = function() {}
// f 는 함수객체 -> 변수처럼 다룰 수 있음
const Bio = (name) => {
const hello = () => console.log("안녕 내이름은 ", name);
return { hello } //객체처럼
//return hello
//return hello()
}
const person = Bio('zeeyoon') //person 이라는 객체에 Hello 라는 함수 프로퍼티를 넣은것
person.hello();
//bio('zeeyoon')();
//bio('zeeyoon');
function createCV() {
let name = "";
let about = "";
function changeName(txt) {
name = txt;
}
function changeAbout(txt) {
about = txt;
}
function print() {
console.log("NAME : ", name);
console.log("ABOUT : ", about);
}
return { changeName, changeAbout, print };
}
// 클로저 만들기 (외부에서 createCV함수 내부의 변수를 저장하는 공간 클로저를 만든다)
// 이력서 1
const cv1 = createCV();
cv1.changeName('zeeyoon');
cv1.changeAbout('개발 경력 6개월');
cv1.print(); //NAME : zeeyoon ABOUT : 개발 경력 6개월
// 이력서 2
const cv2 = createCV();
cv1.changeName('june');
cv1.changeAbout('개발 경력 1년 이상');
cv1.print(); //NAME : june ABOUT : 개발 경력 1년 이상
📍 코드 및 이미지 출처 : 엘리스 아카데미