따라서, async를 붙인 함수의 리턴 값을 받아서 처리하는 곳도 비동기로 처리가 돼야 한다. Promise 객체는 동기적으로 처리되지 않고 항상 비동기적으로 처리되며, 비동기 처리 완료 시의 로직을 붙여야만 기대하는 방식대로 동작할 수 있다.
객체 또는 배열이 참조 타입이라는 걸 활용해서 async가 사용된 함수 안의 값을 리턴 값이 아니라 객체-배열에 담아서 빼올 수 있긴 하다. 하지만, 이 방법이 더 좋은지에 대해서는 아직 유즈 케이스가 많지 않아서 스스로 확신이 서질 않는다.
페이지를 나눠서 SPA 애플리케이션을 개발할 때, 상태를 어디에서 어떻게 관리할지에 대해 다시 고민해봐야겠다. 최상단 App을 두고, 그 밑에 페이지들을 엮은 상황이라면 아무래도 App에서 상태를 관리하기 보다는 페이지들의 index.js 부분에서 관리되는 게 구조 상 더 좋을 수 있을 것 같다.
아직은 많은 상황에 대한 경험이 없기 때문에, 계속 시도해 보면서 하나씩 체득해 가자.
스터디를 위해 모자딥 프로토타입, Strict mode, 빌트인 객체 부분을 다시 읽었다.
19장. 프로토타입
속성을 통해 여러 개의 값을 하나의 단위로 구성한 복합적인 자료구조를 객체라고 한다.
상태(프로퍼티)와 동작(메서드)을 하나의 논리적 단위로 묶어놓은 복합적인 자료구조.
상속은 객체에 정의된 프로퍼티 또는 메서드를 다른 객체가 받아서 그대로 사용할 수 있는 것을 의미한다. 자바스크립트는 프로토타입으로 상속을 구현한다.
프로토타입 객체는 객체의 상위(부모) 역할을 하는 객체로, 다른 객체들에게 공유 프로퍼티를 제공한다.
모든 객체는 하나의 프로토타입과 연결된다. 하나의 프로토타입은 하나의 생성자 함수와 연결된다.
__proto__는 [[Prototype]] 내부 슬롯을 가리키는 접근자 프로퍼티다. getter와 setter 모두 정의돼있다.
__proto__는 객체가 아니라 프로토타입이 갖는다. 객체는 프로터타입에 있는 __proto__ 접근자 프로퍼티를 이용해 내부 슬롯인 [[Prototype]]에 접근이 가능하다.
__proto__ 접근자 프로퍼티가 사용되는 이유는 상호 참조에 의한 프로토타입 체인 생성을 막기 위함이다. 아마도 __proto__ 접근자 프로퍼티 내에 해당 상황을 방지하고 에러를 발생시키는 로직이 추가되어 있을 것으로 예상된다.
프로토타입 체인이 상호 참조되면 프로토타입 체인을 따라 프로퍼티를 검색할 때 무한 루프에 빠지게 된다. 프로토타입 체인 검사를 끝내는 종료 조건이 종점에 위치한 프로토타입일 때로 설정되어 있기 때문이다(원시 타입을 제외한 자바스크립트의 모든 값의 프로토타입 종점은 Object.prototype이다).
__proto__ 접근자 프로퍼티를 직접 코드에서 사용하는 것은 권장되지 않는다. 프로토타입 참조가 필요할 경우엔 getPrototypeOf() 메서드를, 프로토타입 교체를 희망할 땐 setPrototypeOf() 메서드를 사용하자.
Non-constructor인 함수(화살표 함수, 축약 표현으로 정의된 메서드)를 제외한 모든 함수는 prototype 프로퍼티를 갖는다. 이는 생성자 함수로 생성된 인스턴스가 가리킬 프로토타입을 의미한다(인스턴스의 __proto__로 접근 가능한 값일 것으로 예상된다).
모든 프로토타입은 constructor 프로퍼티를 갖는다. 이는 해당 프로토타입을 참조하는 생성자 함수를 의미한다. 프로토타입과 생성자 함수는 언제나 쌍으로 존재한다.
Function 생성자 함수를 통해 만들어진 함수는 렉시컬 스코프를 만들지 않고 전역 스코프인 것처럼 동작한다. 클로저도 만들지 않는다.
리터럴로 생성한 객체와 함수도 생성자 함수를 의미하는 constructor 프로퍼티를 갖는다. 프로토타입 값 상속을 위해 프로토타입 연결이 필요한데, 프로토타입은 언제나 생성자 함수와 쌍으로 존재하기 때문이다.
사용자 지정 생성자 함수는 자신이 평가되어 객체로 생성되는 시점에 프로토타입이 더불어 생성된다. 빌트인 생성자 함수는 전역 객체가 실행될 때 프로토타입을 생성한다.
프로토타입도 객체고, 객체이기 때문에 상위 프로토타입이 존재한다. 즉, 프로토타입은 다른 프로토타입으로 연결된다. 이를 프로토타입 체인이라고 하며, 프로토타입 체인에 있는 모든 상위 프로토타입의 속성들을 상속 가능하다. 프로토타입 체인 검사 순서는 순차적이다.
프로토타입 체인의 최상위는 언제나 Object.prototype이다. Object.prototype의 [[prototype]] 내부 슬롯은 null이다.
상속받아온 속성들은 오버라이딩이 가능하다. 상속받아온 하위 객체에서 오버라이딩 할 시 프로토타입의 값은 변경되지 않는다. 속성 값을 변경하려면 상위 프로토타입의 프로퍼티를 직접 수정해줘야 한다.
프로토타입을 수동으로 변경하는 것은 번거롭고, 실수가 발생할 가능성이 높기 때문에 지양해야 한다.
instanceof 연산자를 사용하면 프로토타입의 인스턴스인지 여부를 확인할 수 있다. instanceof는 프로토타입 체인을 통해 검사를 수행하기 때문에 prototype 객체 참조가 변경되지 않는다면 constructor와 prototype 간의 연결이 깨져도 문제없이 동작한다.
생성자 함수에서도 자신의 내부에서 사용할 프로퍼티/메서드를 소유할 수 있다. 이를 '정적 프로퍼티/메서드'라고 한다. 정적 프로퍼티와 메서드는 프로토타입의 속성이 아니기 때문에 인스턴스에서 참조가 불가능하다.
객체의 프로퍼티 존재 여부 확인에 사용되는 연산자 in은 프로토타입 체인 전체를 검사해서 결과를 뱉는다. 때문에, 검사하고 싶은 객체는 프로퍼티가 없지만 프로토타입에 존재해서 true라는 값을 뱉는 오류가 생길 수 있으니 주의하자. 대신 Object.prototype.hasOwnProperty 메서드를 사용하면 검사하려는 객체로 한정할 수 있다.
20장. Strict mode
Strict mode는 자바스크립트 언어의 문법을 좀 더 엄격히 적용하여 오류를 발생시킬 가능성이 높거나 자바스크립트 엔진의 최적화 작업에 문제를 일으킬 수 있는 코드에 대해 명시적인 에러를 발생시킨다.
Strict mode를 적용하려면 함수 몸체 선두에 use strict;를 추가하면 된다. 반드시 함수 몸체 선두에 위치시켜야 하니 주의하자.
어떤 함수는 Strict mode로 적용되고 다른 함수는 Strict mode가 적용되지 않으면 개발할 때 많은 혼란이 발생할 수 있다. 따라서 Strict mode는 전체 실행 함수를 즉시 실행 함수로 감싼 스크립트 단위로 적용하는 것이 바람직하다.
21장. 빌트인 객체
자바스크립트엔 표준 빌트인 객체, 호스트 객체(브라우저, 노드에서 제공하는 객체), 사용자 정의 객체가 존재한다.
그중 자바스크립트에서 자체적으로 제공하는 빌트인 객체는 약 40여개가 존재한다. 그 중 Math, Reflect, JSON을 제외한 표준 빌트인 객체는 전부 인스턴스를 생성할 수 있는 생성자 함수이다.
빌트인 객체를 생성자 함수로 사용해 만들어진 인스턴스의 프로토타입에는 빌트인 객체의 prototype이 참조된다. 예를 들어, String 빌트인 객체로 생성한 인스턴스의 프로토타입은 String.prototpye이다.
빌트인 객체는 생성자 함수로 사용되지 않을 때에도 유용한 일부 정적 프로퍼티와 메서드를 별도로 제공한다.
원시 타입을 생성하는 빌트인 객체는 원시 타입에 메서드 사용 시 엔진 내부에서 일시적으로 감싸주는 래퍼 객체의 정체다.
전역 객체는 계층적 구조 상 어떤 객체에도 속하지 않은 모든 빌트인 객체(표준 빌트인 객체와 호스트 객체)의 최상위 객체이다. 전역 객체는 어떠한 객체의 프로퍼티도 아니며, 다른 표준 빌트인 객체와 호스트 객체를 프로퍼티로 소유한다.
하나의 전역 객체는 모듈로 분리된 스크립트 파일들 모두에서 공유된다.
빌트인 전역 프로퍼티는 전역 객체의 프로퍼티를 의미한다.
빌트인 저역 함수는 전역에서 호출할 수 있는 빌트인 함수로, 전역 객체의 메서드다. 하지만, 전역 객체, 예를 들어 window는 호출 시 생략될 수 있기 때문에 일반 함수처럼 사용되는 것으로 보일 수 있다. 하지만, 실제론 전역 객체의 메서드다.