📍 오늘배운내용
- 실행컨텍스트 (및 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년 이상
📍 코드 및 이미지 출처 : 엘리스 아카데미