모던 자바스크립트 Deep Dive (Ch.16 ~ Ch.18, Ch.20)

kozi·2023년 7월 17일
0

내용정리

목록 보기
6/7

16장 프로퍼티 어트리뷰트

16.1 내부 슬롯과 내부 메서드

내부 슬롯과 내부 메서드는 자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사양에서 사용하는 의사 프로퍼티와 의사 메서드다.

이중 대괄호 ([[]])로 감싼 이름들.

개발자 직접 접근은 불가능하지만 일부 내부 슬롯과 메서드는 간접적 접근 가능함.

[[Prototype]] 내부 슬롯의 경우, proto를 통해 간접적 접근 가능.


16.2 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체

자바스크립트 엔진은 프로퍼티 생성 시 프로퍼티 어트리뷰트 기본값으로 자동 정의함.

프로퍼티 어트리뷰트는 내부 상태값(meta-property)인 내부 슬롯 [[Value]], [[Writable]], [[Enumerable]], [[Configurable]]이 있음.

Object.getOwnPropertyDescriptor 메서드를 사용해서 간접적으로 확인할 수 있다.
Object.getOwnPropertyDescriptor 메서드는 프로퍼티 디스크립터 객체 봔한함.
존재하지 않는 프로퍼티나 상속받은 프로퍼티에 대해 프로퍼티 디스크립터를 요구하면 undefined가 반환됨.


16.3 데이터 프로퍼티와 접근자 프로퍼티

  • 데이터 프로퍼티

    키와 값으로 구성된 일반적인 프로퍼티.
  • 접근자 프로퍼티

    자체 값은 없고, 다른 데이터 프로퍼티 값 읽거나 저장 시 호출되는, 접근자 함수로 구성된 프로퍼티임.


16.4 프로퍼티 정의

Object.defineProperty 메서드를 사용하면, 프로퍼티의 어트리뷰트를 정의할 수 있다.

인수로는 객체의 참조와 데이터 프로퍼티의 키인 문자열, 프로퍼티 디스크립터 객체를 전달.

Object.defineProperties 메서드 사용하면 여러 개 프로퍼티 한 번에 정의 가능.


16.5 객체 변경 방지

다음과 같은 객체 변경 방지 메서드들이 있음.

  • Object.preventExtensions (객체 확장 금지): 프로퍼티 추가 금지.
  • Object.seal (객체 밀봉): 프로퍼티 추가 금지 + 프로퍼티 삭제, 재정의 금지.
  • Object.freeze (객체 동결): 프로퍼티 추가, 삭제, 재정의 금지 + 프로퍼티 값 쓰기 금지.

중첩 객체까지 동결하려면 모든 프로퍼티에 대해 재귀적으로 Object.freeze 메서드를 호출하면 된다.(deepFreeze)


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

17.1 Object 생성자 함수

new 연산자와 함께 Object 생성자 함수 호출하면 빈 객체를 생성하여 반환한다.

이후 프로퍼티 또는 메서드 추가해서 객체를 완성할 수 있다.

생성자 함수에 의해 생성된 객체를 인스턴스라 한다.

Object 생성자 함수 외에도 String, Number, Boolean, Function, Array, Date, RegExp, Promise 등의 빌트인 생성자 함수가 있다.


17.2 생성자 함수

17.2.1 객체 리터럴에 의한 객체 생성 방식의 문제점

객체 리터럴에 의한 객체 생성 방식은 직관적이고 간편하지만, 동일한 프로퍼티 갖는 객체 여러 개 생성할 때 비효율적.

17.2.2 생성자 함수에 의한 객체 생성 방식의 장점

프로퍼티 구조 동일한 객체 여러 개를 간편하게 생성 가능함.

17.2.3 생성자 함수의 인스턴스 생성 과정

인스턴스 생성 -> 생성된 인스턴스 초기화(인스턴스 프로퍼티 추가 및 초기값 할당)

  1. 인스턴스 생성과 this 바인딩

    암묵적으로 빈 객체(인스턴스) 생성, 이 인스턴스는 this에 바인딩 됨. 이 처리는 런타임 이전에 실행됨.

  2. 인스턴스 초기화

    생성자 함수에 기술된 코드 한 줄씩 실행 -> this에 바인딩된 인스턴스 초기화 함.

  3. 인스턴스 반환

    생성자 함수 내부 처리 끝나면 완성된 인스턴스가 바인딩 된 this를 암묵적으로 반환함.

    this가 아닌 다른 값 반환하는 것은 생성자 함수의 기본 동작을 훼손. 따라서 생성자 함수 내부에서 return 문 반드시 생략해야함.

17.2.4 내부 메서드 [[Call]]과 [[Construct]]

모든 함수 객체는 callable이지만 모든 함수 객체가 constructor인 것은 아니다.

callable이면서 constructor이거나 callable이면서 non-constructor임.

17.2.5 constructor와 non-constructor의 구분

  • constructor: 함수 선언문, 함수 표현식, 클래스(클래스도 함수임)
  • non-constructor: 메서드(ES6 메서드 축약 표현), 화살표 함수

17.2.6 new 연산자

일반 함수와 생성자 함수에 특별한 형식적 차이는 없다.

따라서 생성자 함수는 파스칼 케이스로 명명하여 일반 함수와 구별할 수 있도록 노력한다.

17.2.7 new.target

new.target은 this와 유사하게 constructor인 모든 함수 내부에서 암묵적인 지역 변수와 같이 사용되며 메타 프로퍼티라고 부른다.

new 연산자와 함께 생성자 함수로 호출되면 함수 내부의 new.target은 함수 자신을 가리킴.

new 연산자 없이 일반 함수로 호출된 함수 내부의 new.target은 undefined임.

new.target을 사용할 수 없는 상황이라면 스코프 세이프 생성자 패턴 사용 가능함.


18장 함수와 일급 객체

18.1 일급 객체

다음 조건을 만족하는 객체를 일급 객체라 함.

1. 무명의 리터럴로 생성 가능. 즉, 런타임에 생성 가능.
2. 변수나 자료구조(객체, 배열 등)에 저장 가능.
3. 함수의 매개변수에 전달 가능.
4. 함수의 반환값으로 사용 가능.

일급 객체로서 함수가 가지는 가장 큰 특징은 일반 객체와 같이 함수의 매개변수에 전달 가능하고, 함수의 반환값으로 사용할 수 있다는 것.

함수형 프로그래밍을 가능케 하는 자바스크립트의 장점 중 하나임.

18.2 함수 객체의 프로퍼티

arguments, caller, length, name, prototype 프로퍼티는 일반 객체에는 없는 함수 객체 고유의 프로퍼티다.

18.2.1 arguments 프로퍼티

함수 객체의 arguments 프로퍼티 값은 arguments 객체.

arguments 객체는 함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한 유사 배열 객체로, 함수 내부에서 지역 변수처럼 사용됨. (함수 외부에서 참조 불가)

함수 내부에서 지역 변수처럼 사용할 수 있는 arguments 객체를 참조하는 방식이 권장됨.

arguments 객체는 인수를 프로퍼티 값으로 소유, 프로퍼티 키는 인수의 순서를 나타냄.

arguments 객체의 callee 프로퍼티는 호출되어 함수 자신을 가리키고, arguments 객체의 length 프로퍼티는 인수의 개수를 가리킴.

arguments 객체는 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 때 유용하다.

18.2.2 caller 프로퍼티

ECMAScript 사양에 포함되지 않은 비표준 프로퍼티임.

18.2.3 length 프로퍼티

함수 정의할 때 선언한 매개변수의 개수를 가리킨다.

18.2.4 name 프로퍼티

ES6에서 정식 표준이 됨.

익명 함수 표현식의 경우 ES5에서 name 프로퍼티는 빈 문자열을 값으로 가짐.

ES6에서는 함수 객체를 가리키는 식별자를 값으로 가짐.

18.2.5 __proto__ 접근자 프로퍼티

모든 객체는 [[Prototype]]이라는 내부 슬롯을 가짐.

[[Prototype]]은 객체 지향 프로그래밍의 상속을 구현하는 프로토타입 객체를 가리킴.

hasOwnProperty 메서드: 인수로 전달받은 프로퍼티 키가 객체 고유의 프로퍼티 키인 경우 true 반환, 상속받은 프로토타입의 프로퍼티 키인 경우 false 반환함.

18.2.6 prototype 프로퍼티

생성자 함수로 호출할 수 있는 함수 객체, 즉 constructor만이 소유하는 프로퍼티.
생성자 함수가 생성할 인스턴스의 프로토타입 객체를 가리킴.


20장 strict mode

20.1 strict mode란?

function foo() {
  x = 10;
}
foo();

console.log(x); //?

foo 함수 내에서 선언하지 않은 x 변수에 10을 할당함.
자바스크립트 엔진은 먼저 foo 함수의 스코프에서 x 변수의 선언을 검색하고 실패할 것임.
그 다음 상위 스코프 (예제의 경우 전역 스코프)에서 x 변수 선언 검색함.

전역 스코프에도 선언이 없기 때문에 ReferenceError 발생시킬 것 같지만, 암묵적으로 전역 객체에 x 프로퍼티를 동적 생성함.

전역 객체의 x 프로퍼티는 마치 전역 변수처럼 사용할 수 있음. 이를 암묵적 전역이라 함.

오류 발생시키는 원인 될 가능성 크므로, 반드시 var, let, const 키워드를 사용해서 변수 선언한 다음 사용하자.

ES6에서 도입된 클래스와 모듈은 기본적으로 strict mode가 적용됨.


20.2 strict mode의 적용

strict mode 적용하려면 전역의 선두 또는 함수 몸체의 선두에 'use strict';를 추가한다.


20.3 전역에 strict mode를 적용하는 것은 피하자.

전역에 적용한 strict mode는 스크립트 단위로 적용됨.

strict mode 스크립트와 non-strict mode 스크립트 혼용은 오류 발생시킬 수 있음.

특히, 외부 서드파티 라이브러리를 사용하는 경우 라이브러리가 non-strict mode인 경우도 있기 때문에, strict mode 적용은 바람직하지 않음.

이 경우, 즉시 실행 함수로 스크립트 전체를 감싸서 스코프 구분하고, 즉시 실행 함수의 선두에 strict mode를 적용함.


20.4 함수 단위로 strict mode를 적용하는 것도 피하자.

일부 함수에만 strict mode를 적용하는 것은 바람직하지 않고, 모든 함수에 일일이 strict mode를 적용하는 것은 번거롭다.

strict mode가 적용된 함수가 참조할 함수 외부의 컨텍스트에 strict mode를 적용하지 않으면 또한 문제가 발생할 수 있음.

strict mode는 즉시 실행 함수로 감싼 스크립트 단위로 적용하는 것이 바람직하다.


20.5 strict mode가 발생시키는 에러

  • 암묵적 전역: 선언하지 않은 변수 참조 시 ReferenceError 발생
  • 변수, 함수, 매개변수의 삭제: delete 연산자로 변수, 함수, 매개변수 삭제하면 SyntaxError 발생.
  • 매개변수 이름 중복: 중복된 매개변수 이름 사용 시 SyntaxError 발생
  • With 문의 사용: with 문 사용하면 SyntaxError 발생.

    with 문은 전달된 객체를 스코프 체인에 추가함.

    with 문은 동일한 객체의 프로퍼티를 반복해서 사용할 때 객체 이름을 생략할 수 있어서 코드가 간단해지는 효과가 있지만, 성능과 가독성이 나빠지므로 사용하지 않는 것이 좋다.


20.6 strict mode 적용에 의한 변화

20.6.1 일반 함수의 this

strict mode에서 함수를 일반 함수로 호출하면 this에 undefined가 바인딩 됨.

생성자 함수가 아닌 일반 함수 내부에서는 this를 사용할 필요가 없기 때문.

이 때 에러는 발생하지 않음.

20.6.2 arguments 객체

strict mode에서는 매개변수에 전달된 인수를 재할당하여 변경해도 arguments 객체에 반영되지 않는다.


profile
어제보다 잘하고 싶은 개발자 Kozi 입니다.

1개의 댓글

comment-user-thumbnail
2023년 7월 18일

아주 유용한 정보네요!

답글 달기