TIL(2/7) / JS 3 (실행 컨텍스트, this)
실행 컨텍스트(Execute Context)
실행할 코드에 제공할 환경 정보들을 모아놓은 객체
실행 컨텍스트가 활성화되는 시점에 다음과 같은 일을 한다.
- 선언된 변수를 위로 끌어올린다. (= 호이스팅)
- 외부 환경 정보를 구성한다.
- this 값을 설정한다.
어려울 땐 콘솔로 디버깅하며 확인해보는 것이 도움된다!
예제) 생활코딩 참조
<script>
n0='n0';
var v0='v0';
let l0='l0';
const c0 = 'c0';
console.log(v0, n0, l0, c0);
console.log(window.v0, window.n0, window.l0, window.c0); // v0 n0 undefined undefined
function fn2(){
n2='n2';
console.log(n0, n1, n2);
var v2='v2';
console.log(v0, v2);
// console.log(v1)
let l2='l2';
console.log(l0, l2);
// console.log(l1);
const c2='c2;';
console.log(c0, c2);
// console.log(c1);
}
function fn1(){
n1='n1';
var v1='v1';
let l1='l1';
const c1='c1';
fn2();
}
fn1();
console.log(n2);
// console.log(v2, l2, c2);
</script>
n0 - Global Scope에 쌓인다
var로 선언한 v0도 - Global Scope에 쌓인다
let과 const로 선언한 l0, c0은 Script Scope에 쌓인다
Global에서 가져온 변수는 Window.v0해도 출력된다.
console.log(window.v0, window.n0, window.l0, window.c0);
출력값으로 => v0 n0 undefined undefined 가 뜨는 이유
--> l0, c0은 Script Scope에 존재하기 때문에 window로 불러오면 참조할 값이 없다.
Call Stack에는 전역으로 anonymous(global context, 안 사라짐)함수가 쌓인다
Call Stack에 쌓인 함수로 해당 스코프를 참조할 수 있다.
global execute context에서 실행될 때
a = 1 | Global |
var a = 1 | Global |
let a = 1 | Script |
const a = 1 | Script |
function execute context에서 실행될 때
a = 1 | Global |
var a = 1 | Local |
let a = 1 | Local |
const a = 1 | Local |

this (call, apply, bind)
this : 전역 공간에서 this는 전역 객체를 가리킴 (window 혹은 global)
apply, call, bind : 함수를 상속받아 사용 가능한 메서드들
this 바인딩이란? this가 가리킬 객체를 표출하는 것을 의미
apply와 call은 인수전달 방식만 다를 뿐 동일하게 작동한다.
function getThisBinding(){
console.log(arguments);
return this;
}
const thisArg = { a : 1 };
console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
console.log(getThisBinding.call(thisArg, 1, 2, 3));
// 출력값은 동일
// [Arguments] { '0': 1, '1': 2, '2': 3 }
// { a: 1 }
apply 메서드는 호출할 함수의 인수를 배열로 묶어 전달한다.
call 메서드는 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달한다.
apply, call을 어디에 사용하려고?
-> arguments(위의 예시) 객체와 같은 유사 배열 객체에 배열 메서드를 사용하는 경우!
- arguments 객체는 배열이 아니기 때문에 Array.prototype.slice같은 배열의 메서드를 사용할 수 없다.
하지만 apply와 call 메서드를 이용하면 가능하다.
function converArgsToarray() {
console.log(arguments);
//arguments 객체를 배열로 변환
//Array.prototype.slice를 인수 없이 호출하면 배열의 복사본을 생성한다.
const arr = Array.prototype.slice.call(arguments);
console.log(arr);
return arr;
}
converArgsToarray(1, 2, 3) // [1, 2, 3]
bind 메서드는 apply와 call 메서드와 달리 함수를 호출하지 않는다.
다만 첫 번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성해 반환한다.
- bind는 this를 적용한 함수를반환해준다
- bind를 이용하면 매개변수를 부분 적용시켜준다.
- bind를 이용하면 bound라는 접두어가 붙기 때문에 bind해줘서 반환한 함수를 식별할 수 있다
call이 아니라 bind를 쓰는 이유는 추후에 어떤 방식으로도 사용하기 위해서
const person = {
name: 'Lee',
foo(callback){
// bind 메서드로 callback 함수 내부의 this 바인딩을 전달
setTimeout(callback.bind(this), 100)
}
}
person.foo(function() {
console.log(`Hi my name is ${this.name}.`); // Hi my name is Lee
})
함수 호출 방식 | this 바인딩 |
일반 함수 호출 | 전역 객체 |
메서드 호출 | 메서드를 호출한 객체 |
생성자 함수 호출 | 생성자 함수가 (미래에) 생성할 인스턴스 |
Function.prototype.apply/call/bind 메서드에 의한 간접 호출 |
Function.prototype.apply/call/bind 메서드에 첫 번째 인수로 전달한 객체 |
참조) Deep Dive