우주선

모던 자바스크립트 Deep Dive ― (5) 본문

JavaScript

모던 자바스크립트 Deep Dive ― (5)

선주우 2022. 10. 5. 00:41

 

모던 자바스크립트 Deep Dive ― (5)

 

모던자바스크립트 Deep Dive, 이웅모 지음

 

20장 strict mode 

ES5부터 지원하는 strict mode 는 자바스크립트 언어의 문법을 조금 더 엄격히 적용하여 오류를 발생시킬 가능서잉 높거나 최적화 작업에 문제를 일으킬 수 있는 코드에 대해 명시적인 에러를 발생시킨다.

전역의 선두 또는 함체 몸체의 선두에 'use strict'; 를 추가하여 사용한다.

 

전역에 strict 모드를 적용하는 것은 피해야 한다. 

다른 스크립트에 영향을 줄 수 있고, 외부 서드파티 라이브러리가 non-strict mode일 수도 있기 떄문이다.  

함수 단위로 적용하는 것도 피해야 한다. 

번거롭기도 하거니와 strict mode의 함수가 참조할 외부 함수의 컨텍스트에 strict mode를 적용하지 않는다면 문제가 발생하기 때문이다.

 

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

 

20.5 strict mode 가 발생시키는 에러 

1) 암묵적 전역 : 선언하지 않은 변수를 참조하면 ReferenceError

2) 변수, 함수, 매개변수의 삭제 : delete 연산자로 삭제할 경우 SyntaxError

3) 매개변수 이름의 중복시 SyntaxError

 

20.6 strict mode 적용에 의한 변화 

1) 일반 함수의 this : 일반 함수의 this에 undefined가 바인딩된다. 

2) arguments 객체 : 매게변수에 전달된 인수를 재할당해도 arguments객체에 반영되지 않는다. 

 

 

21장 빌트인 객체 

ES5부터 지원하는 strict mode 는 자바스크립트 언어의 문법을 조금 더 엄격히 적용하여 오류를 발생시킬 가능서잉 높거나 최적화 작업에 문제를 일으킬 수 있는 코드에 대해 명시적인 에러를 발생시킨다.

 

21.1 자바스크립트 객체의 분류

자바스크립트 객체는 표준 빌트인 객체, 호스트 객체, 사용자 정의 객체로 분류할 수 있다.

 

표준 빌트인 객체 : ECMAScript 에 정의된 객체. 어플리케이션 전역의 공통 기능. 전역 변수처럼 언제나 참조 가능

호스트 객체 : ECMAScript 에 정의되어 있지 않지만 자바스크립트 실행 환경 (브라우저, Node.js) 에서 추가로제공하는 객체

사용자 정의 객체 : 사용자가 직접 정의한 객체 

 

21.2 표준 빌트인 객체, 21.3 원시값과 래퍼 객체 

Math, Reflect, JSON을 제외한 표준 빌트인 객체 (Object, String, Number ... ) 는 모두 인스턴스를 생성 할 수 있는 객체다. 

문자열이나 숫자, 불리언 등의 원시값이 있는데도 표준 빌트인 생성자 함수가 존재하는 이유는 무엇일까 ? 

이는 원시값의 경우 원시값에 대해 마치 객체처럼 마침표 표기법으로 접근하면 자바스크립트 엔진이 일시적으로 원시값을 연관된 객체로 변환해 주기 떄문이다. 원시값을 객체처럼 사용하면 자바스크립트 엔진은 암묵적으로 연관된 객체를 생성하여 생성된 객체로 프로퍼티에 접근하거나 메서드를 호출하고 다시 원시값으로 되돌린다. 이때 생성되는 임시 객체를 래퍼 객체Wrapper Object 라고 한다.

 

순서는 다음과 같다.

1. 문자열에 마침표 표기법으로 접근(str.length) 

2. 래퍼 객체인 String 생성자 함수의 인스턴스가 생성

3. 문자열은 래퍼 객체의 [[StringData]] 내부 슬롯에 할당

4. String.prototype의 메서드를 상속받아 사용

5. 처리 종료시 원시값으로 회귀 

6. 래퍼 객체는 가비지 컬렉터가 수집 

 

래퍼 객체를 생성하지 않는 원시값은 null, undefined 이며 이 두 값을 객체처럼 사용하면 에러가 발생한다. 

 

21.4 전역 객체

전역 객체는 코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다도 머저 생성하는 특수한 객체이며, 어떤 객체에도 속하지 않은 최상위 객체다.

계층적 구조상 어떤 객체이도 속하지 않은 모든 빌트인 객체의 최상위 객체다. 전역 객체 자신은 어떤 객체의 프로퍼티도 아니다.

특징

1) 개발자가 의도적으로 생성할 수 없다. 

2) 전역 객체의 프로퍼티를 참조할 때 window(global)를 생략할 수 있다.

3) 모든 표준 빌트인 객체를 프로퍼티로 가지고 있다.

4) 자바스크립트 실행 환경에 따라 호스트 객체를 갖는다. 

5) let, const 로 선언한 전역 변수는 전역 객체의 프로퍼티가 아니다. 개념적인 블록(전역 렉시컬 환경의 선언전 환경 레코드)내에 존재한다.

 

빌트인 전역 프로퍼티 :Infinity , NaN , undefined 

빌트인 전역 함수 : eval(사용하지 말 것), inNaN, parseFloat, parseInt, encodeURI / decodeURI , encodeURIComponent / decodeURIComponent 

encodeURI : 완전한 URI를 문자열로 전달받아 이스케이프 처리를 위해 인코딩한다. 인코딩이란 URI의 문자들을 이스케이프 처리하는 것을 의미하는데, 이스케이프 처리란 어떤 시스템에서도 읽을 수 있는 아스키 문자 셋으로 변환하는 것이다. 

encodeURIComponent : 전달된 문자열 중 쿼리스트링 구분자로 사용되는 = , ? , & 까지 인코딩한다.(encodeURI는 = , ? , & 인코딩하지 않음 ) 

 

암묵적 전역은 전역 객체의 프로퍼티로 추가되었을 뿐 변수가 아니므로 호이스팅이 발생하지 않는다.

 

 

22장 this 

22.1 this 키워드

this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수다. this가 가리키는 값, this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다. 

1) 전역에서 this 는 전역 객체 window를 가리킨다.

2) 일반 함수 내에서 this는 전역 객체 window를 가리킨다. ( strict mode라면 undefined )

3) 메서드 내부에서 this는 메서드를 호출한 객체를 가리킨다.

4) 생성자 함수 내에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다.

 

22.2 함수 호출 방식과 this 바인딩

일반 함수로 호출하면 함수 내부의 this에는 전역 객체가 바인딩된다. (non-strict-mode)

메서드 내부의 중첩 함수나 콜백 함수의 this 바인딩을 메서드의 this 바인딩과 일치시키기 위해서는 

1. this바인딩을 변수에 할당하거나 , 2. this를 명시적으로 바인딩할 수 있는 메서드 (Function.prototype.apply,call,bind 등)을 이용하거나 , 3.화살표 함수를 사용하여 this바인딩을 일치시킨다. 

 

메서드 내부의 this에는 메서드를 호출한 객체가 바인딩된다. 

그래서 this에 바인딩될 객체는 호출 시점에 결정된다.

 

생성자 함수 내부의 this에는 생성자 함수가 미래에 생성할 인스턴스가 바인딩된다. 

 

 

 

23장 실행 컨텍스트

23.1 소스코드의 타입

ECMAScript 사양은 소스코드를 4가지 타입으로 구분하며, 소스코드는 전역 실행 컨텍스트를 생성한다.

1) 전역 코드 타입

전역에 존재하는 소스코드로서 최상위 스코프인 전역 스코프를 생성

2) 함수 코드 타입

함수 내부에 전재하는 소스코드로서 지역 스코프를 생성하고 지역변수, 매개변수, arguments 객체를 관리

3) eval 코드 타입 : eval 함수에 인수로 전달되어 실행되는 소스코드 

4) 모듈 코드 타입 : 모듈 내부에 존재하는 소스코드. 모듈 내부의 함수, 클래스 등의 내부 코드는 비포함

 

23.2 소스코드의 평가와 실행 

모든 소스코드는 실행에 앞서 평가 과정을 거치며 "소스코드의 평가" 와 "소스코드의 실행" 과정으로 나누어 처리한다.

1) 소스코드의 평가

실행 컨텍스트를 생성한다. 변수,함수 등의 선언문만 먼저 실행한다. 생성된 변수와 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프에 등록한다.

2) 소스코드의 실행 

소스코드의 평가가 끝나면 런타임이 시작된다. 변수나 함수의 참조를 실행 컨텍스트가 관리하는 스코프에서 검색하여 취득하고, 값의 변경 등 소스코드의 결과는 실행 컨텍스트가 관리하는 스코프에 등록한다.

 

22.3 실행 컨텍스트의 역할 

실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리한다. 

식별자(변수,함수,클래스 등)를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘으로, 모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다. 식별자와 스코프는 실행 컨텍스트의 렉시컬 환경으로 관리하고, 실행 순서는 실행 컨텍스트 스택으로 관리한다.

 

22.4 실행 컨텍스트 스택 

코드의 실행 순서를 관리한다. 

예시로 전역과 foo라는 함수가 있다면 실행 컨텍스트 스택은 '빈 컨텍스트 > 전역 실행 컨텍스트 > foo함수 실행 컨텍스트 > 전역 실행 컨텍스트 > 빈 컨텍스트 ' 순서를 가진 스택이 될 것이다. 

 

22.5 렉시컬 환경

렉시컬 환경은 식별자와 식별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트다. 실행 컨텍스트 스택이 코드 실행 순서를 관리한다면, 렉시컬 환경은 스코프와 식별자를 관리한다. 스코프를 구분하여 식별자를 등록하고 관리하는 저장소 역할을 한다. 두 개의 컴포넌트로 구성된다.

1. 환경 레코드 : 스코프에 포함된 식별자를 등록하고 바인딩된 값을 관리하는 저장소 

2. 외부 렉시컬 환경에 대한 참조 : 상위 스코프, 상위 코드의 렉시컬 환경에 대한 참조 

 

23.6 실행 컨텍스트의 생성과 식별자 검색 과정 

예시로 전역에 변수와 함수가 정의되어 있고, 함수를 호출하는 코드가 있다고 하자. 이 코드는 어떻게 동작할까? 

1) 전역 객체 생성 -> 2) 전역 코드 평가 -> 3) 전역 코드 실행 -> 4) 함수 코드 평가 -> 5) 함수 코드 실행 

순서일 것이다. 

 

1) 전역 객체 생성 

2) 전역 코드 평가 

2-1) 전역 실행 컨텍스트 생성 : 비어있는 전역 실행 컨텍스트를 생성하여 실행 컨텍스트 스택에 푸시

2-2) 전역 렉시컬 환경 생성 : 렉시컬 환경을 생성하고 전역 실행 컨텍스트에 바인딩한다.

        a) 객체 환경 레코드 : var 키워드로 선언한 전역 변수와 함수 선언문으로 정의한 전역 함수, 표준 빌트인 객체를 관리한다.

                                         var 키워드나 전역 함수의 경우 전역 객체의 프로퍼티와 메서드가 된다.

        b) 선언적 환경 레코드 : let, const 키워드로 선언한 전역 변수

        c) this바인딩 : 전역 환경 레코드의 내부 슬롯에 this 가 바인딩된다. 

        d) 외부 렉시컬 환경에 따른 참조 결정  

3) 전역 코드 실행 : 전역 코드가 순차적으로 실행되며 함수가 호출된다. 

4) 함수 코드 평가

4-1) 함수 실행 컨텍스트 생성 : 함수 렉시컬 환경이 완성된 뒤 다음 실행 컨텍스트 스택에 푸시된다 ( 전역은 빈 컨텍스트였다)

4-2) 함수 렉시컬 환경 생성 : 함수 환경 레코드 생성, this 바인딩, 외부 렉시컬 환경에 대한 참조 결정

( 자바스크립트는 함수를 어디서 호출했는지가 아닌 어디에 정의했는지에 따라 상위 스코프를 결정하는 정적 언어다. 함수의 상위 스코프를 함수 객체의 내부 슬롯에 저장한다.  )

5) 함수 코드 실행  

6) 함수 실행 종료 

7) 전역 코드 실행 종료 

 

23.7 실행 컨텍스트와 블록 레벨 스코프 

var 키워드로 선언한 변수는 오로지 코드 블록만 지역 스코프로 인정하는 함수 레벨 스코프를

let, const는 모든 코드 블록을 지역 스코프로 인정하는 블록 레벨 스코프를 따른다. 

이를 위해 선언적 환경 레코드를 갖는 렉시컬 환경을 생성하여 기존 전역 렉시클 환경을 교체한다. for 문의 경우 코드 블록이 실행될 때마다 식별자의 값을 유지해야 한다. 그떄마다 독립적인 렉시컬 환경을 생성하여 식별자의 값을 유지한다. ( 24장 클로저 )  

Comments