[TIL] 2022.04.08

Minsu Han·2022년 4월 8일
0

TODAY I LEARNED

목록 보기
31/46

오늘 한 일

  • 모던 자바스크립트 Deep Dive
  1. 스코프
  2. 전역 변수의 문제점
  3. let, const 키워드와 블록 레벨 스코프
  4. 프로퍼티 어트리뷰트
  5. 생성자 함수에 의한 객체 생성

배운 것

13. 스코프

  • 스코프: 식별자가 유효한 범위
  • 자바스크립트 엔진은 스코프를 통해 어떤 변수를 참조해야하는지 결정함
  • 스코프를 통해 식별자인 변수 이름의 충돌을 방지하여 같은 이름의 변수를 사용할 수 있게 한다(namespace)
  • 변수 참조 시 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색한다
  • 블록 레벨 스코프: 모든 코드 블록이 지역 스코프를 생성
  • 함수 레벨 스코프: var 키워드로 선언된 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정함
  • 자바스크립트는 렉시컬 스코프를 따르므로 함수를 어디서 호출했는지가 아닌(동적 스코프) 함수를 어디서 정의했는지에 따라 상위 스코프를 결정한다.

14. 전역 변수의 문제점

  • 함수 내부에서 선언한 변수는 함수가 호출된 직후 함수 몸체의 코드 실행 이전에 자바스크립트 엔진에 의해 먼저 실행됨
  • 변수의 생명 주기는 메모리 공간 확보 시점부터 메모리 공간이 해제되어 가용 메모리 풀에 반환되는 시점까지다
  • 스코프 역시 누군가 스코프를 참조하고 있으면 소멸하지 않고 생존하게 된다
  • 호이스팅은 스코프 단위로 동작하며, 변수 선언이 스코프의 선두로 끌어올려진 것처럼 동작하는 자바스크립트 고유 특징이다
  • 전역 객체: 코드 실행 전에 자바스크립트 엔진에 의해 가장 먼저 생성되는 특수 객체 (클라이언트 사이드에서는 window, 서버사이드 환경에서는 global)
  • 변수의 스코프는 좁을수록 좋다. (var 전역 변수의 생명 주기는 전역 객체의 생명 주기와 같을 정도로 길다)
  • 전역 변수 사용을 억제하는 방법: 즉시 실행 함수, --네임스페이스 객체--, 모듈 패턴 등

15. let, const 키워드와 블록 레벨 스코프

  • let 키워드는 var 키워드와 달리 변수 중복 선언이 금지, 블록 레벨 스코프를 가진다
  • let 키워드로 선언한 변수는 선언 단계는 런타임 이전에 실행되지만 초기화 단계는 변수 선언문에 도달했을때 실행된다
  • let 키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 아니다
  • const 키워드로 선언된 변수에 객체를 할당한 경우 재할당(참조값 변경)만 불가하고 객체에 대한 변경은 가능하다
  • 변수 선언에는 기본적으로 const를 사용하고 let은 재할당이 필요한 경우에 한정해 사용하는 것이 좋다

16. 프로퍼티 어트리뷰트

  • 내부 슬롯과 내부 메서드([[...]]): 자바스크립트 엔진의 구현 알고리즘을 설명하는 의사 프로퍼티와 의사 메소드
    개발자가 직접 접근할 수는 없지만 간접 접근 방식을 일부 제공
  • 자바스크립트 엔진은 프로퍼티 생성 시 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의한다. 프로퍼티 상태에는 [[Value]], [[Writable]], [[Enumerable]], [[Configurable]] (값, 값 갱신가능 여부, 열거 가능 여부, 재정의 가능 여부)가 있다
  • Object.getOwnPropertyDescriptor 메서드는 프로퍼티 어트리뷰트 정보를 제공하는 Property Descriptor 객체를 반환한다
  • 데이터 프로퍼티: [[Value]], [[Writable]], [[Enumerable]], [[Configurable]]
  • 접근자 프로퍼티: [[Get]], [Set], [[Enumerable]], [[Configurable]]
  • Object.defineProperty 메서드를 사용하면 프로퍼티 어트리뷰트를 정의할 수 있다
  • 객체 변경 방지 메서드: Object.preventExtensions, Object.seal, Object.freeze
  • 위 메서드들은 직속 프로퍼티만 변경을 방지하고 중첩 객체까지는 영향을 주지 못한다(얕은 변경 방지)
  • 객체의 중첩 객체까지 동결하여 변경이 불가능한 읽기 전용의 불변 객체를 구현하려면 객체를 값으로 갖는 모든 프로퍼티에 대해 재귀적으로 Object.freeze 메서드를 호출해야 한다

17. 생성자 함수에 의한 객체 생성

  • 생성자 함수에 의한 객체 생성 방식은 인스턴스 생성을 위한 템플릿(클래스)처럼 프로퍼티 구조가 동일한 객체 여러 개를 간편하게 생성할 수 있다
  • 함수 객체는 일반 객체가 가지고 있는 내부 슬롯과 내부 메소드는 물론, 함수로서 동작하기 위해 함수 객체만을 위한 내부 슬롯과 내부 메소드를 추가로 가지고 있다
  • 일반적인 함수로서 호출 시 [[Call]]이, 생성자 함수로서 호출(new 키워드 사용) 시 [[Construct]]가 호출된다. 그리고 그 함수 내부의 this는 각각 전역 객체, 생성자 함수가 생성할 인스턴스를 가리킨다.
  • new 연산자와 함께 호출하는 함수는 non-constructor가 아닌 constructor이어야 한다.
  • 생성자 함수가 new 연산자 없이 호출되는 것을 방지하기 위해 파스칼 컨벤션을 사용한다 하더라도 실수 위험성을 방지하기 위해 ES6에서는 new.target을 지원한다. new.target을 사용하여 new 연산자와 생성자 함수로서 호출했는지 확인할 수 있다. (일반 함수로 호출된 경우 new.target이 undefined를 반환)
profile
기록하기

0개의 댓글