console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 10;
console.log(y); // 10
호이스팅 후
// y는 호이스팅되지만 초기화 전 접근 시 ReferenceError 발생
let y;
console.log(y); // ReferenceError
y = 10;
console.log(y); // 10
greet(); // 'Hello, world!'
function greet() {
console.log('Hello, world!');
}
호이스팅 후
function greet() {
console.log('Hello, world!');
}
greet(); // 'Hello, world!'
greet(); // TypeError: greet is not a function
var greet = function() {
console.log('Hello, world!');
};
호이스팅 후
var greet;
greet(); // TypeError: greet is not a function
greet = function() {
console.log('Hello, world!');
};
console.log(x); // undefined
var x = 5;
console.log(x); // 5
위 코드가 호이스팅된 동작은 밑에와 같다
var x;
console.log(x); // undefined
x = 5;
console.log(x); // 5
VariableEnvironment와 LexicalEnvironment은 둘 다 스코프와 관련된 내부 개념으로, 코드 실행 시 변수와 함수 선언을 추적하고 관리하는 데 중요한 역할을 한다. 이 둘을 나누어 사용하는 이유는 JavaScript의 다양한 기능과 실행 방식에서 오는 필요성 때문
Environment Record: 현재 스코프에서 정의된 모든 변수와 함수의 매핑(키-값 쌍)을 저장.
Outer Lexical Environment Reference: 외부 스코프를 참조. 이 참조를 통해 현재 스코프가 포함된 외부 환경에 접근할 수 있다.
왜 나누어 사용하는가?
var, let, const의 차이
function example() {
var x = 10; // VariableEnvironment에서 관리
let y = 20; // LexicalEnvironment에서 관리
if (true) {
var x = 30; // 같은 VariableEnvironment 내에서 재할당
let y = 40; // 새로운 LexicalEnvironment 블록 생성
console.log(x); // 30
console.log(y); // 40
}
console.log(x); // 30 (블록 외부에서 접근 가능)
console.log(y); // 20 (블록 외부의 y는 다른 LexicalEnvironment에서 관리됨)
}
example();
클래스 선언도 호이스팅되지만, 'let'과 'const'처럼 선언 전에 사용하면 ReferenceError가 발생한다.
const myInstance = new MyClass(); // ReferenceError: Cannot access 'MyClass' before initialization
class MyClass {
constructor() {
this.name = 'MyClass Instance';
}
}
기본 함수 호출 => 바인딩 (x)
function exampleFunc() {
console.log(this);
}
exampleFunc(); // 브라우저에서는 window, Node.js에서는 global
메서드 호출 => 바인딩 (o)
const obj = {
name: 'Javascript',
greet: function() {
console.log(this.name);
}
};
obj.greet(); // 'Javascript' 출력
생성자 호출 => 바인딩(o)
function Person(name) {
this.name = name;
}
const person = new Person('WY');
console.log(person.name); // 'WY' 출력
function greet() {
console.log(this.name);
}
const person = { name: 'Battle' };
greet.call(person); // 'Battle' 출력
greet.apply(person); // 'Battle' 출력
=> 즉시 실행 함수여서 값을 즉시 받음.
라는 차이가 있다.
function greet() {
console.log(this.name);
}
const person = { name: 'Duran' };
const greetPerson = greet.bind(person);
greetPerson(); // 'Duran' 출력
=> 바인드 시켜줌으로 this를 고정시키는 새로운 함수를 반환 한다.
즉시 실행이 아니여서 원할때 바인딩 된 this를 가져와서 사용 가능.
const obj = {
name: 'Eden',
greet: function() {
const innerGreet = () => {
console.log(this.name);
};
innerGreet();
}
};
obj.greet(); // 'Eden' 출력
=> 화살표 함수는 this 바인딩을 가지지 않음. 화살표 함수가 정의된 렉시컬 환경의 this를 상속받음. 위 예제에서는 greet 함수가 정의된 객체 obj의 this를 상속 받음.