실행할 코드에 제공할 환경 정보들을 모아놓은 객체로
다음과 같은 요소로 구성됨:
- record (environmentRecord): 현재 컨텍스트와 관련된 코드의 식별자 정보 저장
- outer (outerEnvironmentReference): 상위 스코프 참조
- record (environmentRecord)
- outer (outerEnvironmentReference)
Des: 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장(수집)
매개변수 및 변수는 선언부를 호이스팅 합니다
🔹 변수 및 함수 호이스팅
1) 변수 호이스팅 예제
function a(x) {
console.log(x); // action point 1
var x;
console.log(x); // action point 2
var x = 2;
console.log(x); // action point 3
}
a(1);
🔹 매개변수 적용 후
function a() {
var x = 1;
console.log(x);
var x;
console.log(x);
var x = 2;
console.log(x);
}
a(1);
🔹 호이스팅 적용 후
function a() {
var x;
var x;
var x;
x = 1;
console.log(x);
console.log(x);
x = 2;
console.log(x);
}
a(1);
📌 변수 선언 (var x)는 호이스팅되지만, 할당(x = 2)은 호이스팅되지 않음
🔹 함수 선언과 함수 표현식의 호이스팅 차이
1) 함수 선언문 (Function Declaration)
console.log(sum(1, 2)); // 정상 실행됨
function sum(a, b) {
return a + b;
}
✔ 함수 선언문은 전체가 호이스팅됨 → 정상 실행 가능
2) 함수 표현식 (Function Expression)
console.log(multiply(3, 4)); // ❌ 오류 발생 (변수 선언만 호이스팅됨)
var multiply = function(a, b) {
return a * b;
};
✔ 함수 표현식에서는 변수 선언(var multiply)만 호이스팅되고, 함수 할당부는 원래 자리에 남아 있음 → undefined is not a function 오류 발생
📌 협업이 많고 복잡한 코드일수록 함수 표현식을 활용하는 것이 유지보수에 유리함
Des: outer는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조하며, 항상 outer는 오직 자신이 선언된 시점의 LexicalEnvironment를 참조하고 있으므로, 가장 가까운 요소부터 차례대로 접근 가능
🔹 스코프 체인 예제
var a = 1;
var outer = function() {
var inner = function() {
console.log(a);
var a = 3;
};
inner();
console.log(a);
};
outer();
console.log(a);
📌 예상 출력 결과
undefined
1
1
4. this (this binding)
🔹 전역 공간에서의 this ->
브라우저 환경: window
Node.js 환경: global
🔹 함수와 메서드에서의 this 차이
실행주체가 있으면 메서드(this는 실행주체), 없으면 함수(this는 전역)
생성자 함수 내부의 this는 새롭개 생성된 인스턴스를 의미
예제
var fullname = 'Ciryl Gane';
var fighter = {
fullname: 'John Jones',
opponent: {
fullname: 'Francis Ngannou',
getFullname: function () {
return this.fullname;
}
},
getName: function() {
return this.fullname;
},
getFirstName: () => {
return this.fullname.split(' ')[0];
},
getLastName: (function() {
return this.fullname.split(' ')[1];
})()
}
console.log('Not', fighter.opponent.getFullname(), 'VS', fighter.getName());
// ✅ Not Francis Ngannou VS John Jones
console.log('It is', fighter.getName(), 'VS', fighter.getFirstName(), fighter.getLastName);
// ✅ It is John Jones VS Ciryl Gane
📌 분석
console.log('Not', fighter.opponent.getFullname(), 'VS', fighter.getName()); // Not, Francis Ngannou , John Jones
// 1. fighter.opponent.getFullname()는 메서드이고 메서드의 this는 실행주체.
// 실행주체는 fighter.opponent이고 따라서 이 객체의 프로퍼티인 fullname은 Francis Ngannou
// 2. fighter.getName()은 fighter의 메서드임으로 this는 fighter. 따라서 this.fullname 은 fighter.fullname John Jones
console.log('It is', fighter.getName(), 'VS', fighter.getFirstName(), fighter.getLastName); // It is John Jones VS Ciryl Gane
// 1. fighter.getName()은 fighter의 메서드 임으로 this는 fighter 따라서 this.fullname 은 fighter.fullname John Jones
// 2. 화살표 함수는 this binding 안함. 이전의 값-상위값-이 유지됨. 따라서 전역 객체를 가리킴
// 3. 즉시 실행함수는 호출 주체가 fighter가 아니라 .. fighter.getLastName 부분을 대체했다.. 따라서 이것도 this가 전역객체를 바라봄.
🔹 call(), apply(), bind() -> 함수에서 호출할 수 있는 메서드로, 명시적으로 this를 바꿀 수 있다. 함수, 메서드 모두 this 변경 가능
call() → 즉시 실행하며 this를 변경
apply() → call()과 동일하지만 인수를 배열로 전달
bind() → 새로운 함수 반환 (즉시 실행되지 않음)
넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하는 메서드
1. 함수에 this를 미리 적용
2. 부분 적용 함수 구현할 때 용이
var func = function (a, b, c, d) {
console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // window 객체 출력
// call
func.call({ x: 1 }, 4, 5, 6}; // { x: 1 } 4 5 6
// apply
obj.method.apply({ a: 4 }, [5, 6]); // 4 5 6
// ✅ `this`를 명시적으로 설정
var bindFunc1 = func.bind({ x: 1 });
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8
// ✅ 부분 적용 함수 구현
var bindFunc2 = func.bind({ x: 1 }, 4, 5);
bindFunc2(6, 7); // ✅ { x: 1 } 4 5 6 7
bindFunc2(8, 9); // ✅ { x: 1 } 4 5 8 9
V8 JavaScript 엔진을 기반으로 JavaScript를 실행할 수 있도록 만든 런타임 환경
원래 JavaScript는 브라우저에서만 실행되었지만, Node.js를 통해 서버에서도 실행 가능
런타임 환경이란?
JavaScript 프로그램이 실행되는 환경
예) Node.js 환경(vscode에서 실행), 브라우저 환경(Chrome에서 실행)