Javascript 공부 - 004

변우영·2024년 8월 16일

Javascript

목록 보기
4/7

<목표>

  1. 호이스팅 과 VE,LE
  2. this binding

호이스팅

  • 변수와 함수 선언이 해당 스코프의 최상단으로 올라가는 것, 그래서 실제 코드 작성 순서와는 다르게 동작 할 수 있음.

var

  • 'var'로 선언된 변수는 선언이 끌어올려지지만, 값의 할당은 그렇지 않다. 따라서 선언된 변수는 호이스팅되어 함수나 스코프의 최상단에 있는 것처럼 인식되지만, 실제로는 undefined로 초기화됨을 주의 해야한다.

let과 const로 선언된 변수

  • 'let'과 'const'로 선언된 변수도 호이스팅되지만, 'var'와 달리 초기화되기 전에 접근 할 수 없기 때문에 오류가 발생한다.
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

VariableEnvironment와 LexicalEnvironment은 둘 다 스코프와 관련된 내부 개념으로, 코드 실행 시 변수와 함수 선언을 추적하고 관리하는 데 중요한 역할을 한다. 이 둘을 나누어 사용하는 이유는 JavaScript의 다양한 기능과 실행 방식에서 오는 필요성 때문

  • Lexical Environment (렉시컬 환경)
    코드 실행 중 변수와 함수의 식별자(이름)를 정의하고, 그 식별자가 가리키는 값을 추적하는 데 사용됨. 기본적으로 함수나 블록이 실행될 때마다 새로운 렉시컬 환경이 생성된다.

Environment Record: 현재 스코프에서 정의된 모든 변수와 함수의 매핑(키-값 쌍)을 저장.
Outer Lexical Environment Reference: 외부 스코프를 참조. 이 참조를 통해 현재 스코프가 포함된 외부 환경에 접근할 수 있다.

  • Variable Environment (변수 환경)
    VariableEnvironment도 LexicalEnvironment와 유사하게 코드 실행 중 변수와 함수의 선언을 추적. 차이점은 VariableEnvironment는 함수 실행 시점에서의 변수를 추적하기 위해 사용되며, 특히 var로 선언된 변수의 스코프를 관리하는 데 주로 사용됨.

왜 나누어 사용하는가?

  • 함수 선언과 블록 스코프
    함수의 선언과 실행은 VariableEnvironment와 LexicalEnvironment을 다르게 사용된다. 함수는 선언 시점의 스코프 정보를 기억하며, 이 정보가 실행 시점에 어떻게 접근될지를 결정하는데 이 과정에서 VariableEnvironment는 함수 스코프의 초기화 단계에서 중요한 역할을 한다. 반면, LexicalEnvironment는 실행 중에 변수와 함수의 참조를 관리한다.

var, let, const의 차이

  • var로 선언된 변수는 함수 스코프에만 종속되지만, let과 const로 선언된 변수는 블록 스코프에 종속된다. 이때 VariableEnvironment는 함수 스코프 내에서 var 변수를 관리하고, LexicalEnvironment는 블록 스코프 내에서 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';
  }
}

This Binding

  • 함수 컨텍스트

    함수의 호출되는 방식에 따라 this의 값이 달라짐.

기본 함수 호출 => 바인딩 (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' 출력
  • 명시적 바인딩

  • 'call','apply' 함수를 호출하여 this를 특정 객체로 지정
function greet() {
  console.log(this.name);
}

const person = { name: 'Battle' };

greet.call(person); // 'Battle' 출력
greet.apply(person); // 'Battle' 출력
  • call: 함수의 인수를 개별적으로 전달해야함.
  • apply: 함수의 인수를 배열로 전달해야함.

=> 즉시 실행 함수여서 값을 즉시 받음.

라는 차이가 있다.

  • 'bind'
function greet() {
  console.log(this.name);
}

const person = { name: 'Duran' };

const greetPerson = greet.bind(person);
greetPerson(); // 'Duran' 출력

=> 바인드 시켜줌으로 this를 고정시키는 새로운 함수를 반환 한다.
즉시 실행이 아니여서 원할때 바인딩 된 this를 가져와서 사용 가능.

  • 화살표 함수의 'this'

const obj = {
  name: 'Eden',
  greet: function() {
    const innerGreet = () => {
      console.log(this.name);
    };
    innerGreet();
  }
};

obj.greet(); // 'Eden' 출력

=> 화살표 함수는 this 바인딩을 가지지 않음. 화살표 함수가 정의된 렉시컬 환경의 this를 상속받음. 위 예제에서는 greet 함수가 정의된 객체 obj의 this를 상속 받음.

profile
개발자로 한걸음!

0개의 댓글