모던 자바스크립트 Deep Dive Ch.13~17

Jayde·2023년 1월 31일
0

2023-1 studyJs

목록 보기
4/7
post-thumbnail

Ch13. 스코프

스코프 : 식별자 유효 범위
변수 이름 충돌 방지

var은 한 스코프 내 중복 선언이 가능하나 let/const는 불가

  • 스코프의 종류
    1. 전역과 전역 스코프
    어디서든 참조 가능

    2. 지역과 지역 스코프
    자신의 지역 스코프와 하위 지역 스코프에서 유효

  • 스코프 체인
    지역 스코프는 함수에 따라 중첩됨 → 계층 구조
    스코프 체인 : 스코프를 계층적으로 연결한 것

    변수 참조 시 변수를 참조하는 스코프에서 상위 방향으로 변수를 검색함
    (하위 스코프에서 유효한 변수를 상위에서 참조할 수 없음)

  • 함수 레벨 스코프
    : 함수의 코드 블록만을 지역 스코프로 인정함

    //예시
    var x = 1;
    
    if (true) { var x = 10; }
    
    console.log(x); //x를 전역 변수로 침 -> 의도치 않은 재할당
  • 렉시컬 스코프(= 정적 스코프)
    함수를 어디서 정의했느냐에 따라 상위 스코프 결정

    var x = 1;
    
    function foo() {
       var x = 10;
       bar();
    }
    
    function bar() { console.log(x); }
    
    foo(); //bar이 전역 함수이므로 1
    bar(); //1

Ch14. 전역 변수의 문제점

  • 변수의 생명 주기
    전역 : 애플리케이션의 생명주기와 동일 / js 엔진에 의해 런타임 이전 단계에 실행됨
    지역 : 함수의 생명주기와 동일 / js 엔진에 의해 함수 몸체 코드 실행 이전에 실행됨
    누군가 참조하고 있으면 할당된 메모리를 계속 확보한 상태로 유지

  • 전역 변수의 문제점
    1. 암묵적 결합의 허용
    암묵적 결합 : 전역 변수를 어디서든 참조 및 변경 가능
    2. 긴 생명 주기
    메모리 리소스 오래 소비
    변수 이름 중복 가능성 → 의도치 않은 재할당
    3. 스코프 체인 상에서 종점에 존재
    변수 검색 시 가장 마지막에 검색됨 = 검색 속도가 가장 느림
    4. 네임스페이스 오염
    파일이 분리되어 있어도 하나의 전역 스코프 공유 → 예상치 못한 결과 초래

  • 전역 변수 사용을 억제하는 법
    1. 반드시 사용해야하는 경우 제외 지역 변수 사용
    2. 즉시 실행 함수
    모든 코드를 즉시 실행함수로 감싸서 전역 변수 사용 제한
    3. 네임스페이스 객체
    네임스페이스 역할을 할 객체 생성 후 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가
    식별자 충돌 방지는 가능하나 네임스페이스 객체 자체가 전역 변수에 해당되어 별로임

  • 모듈 패턴
    : 클래스를 모방해 관련 있는 변수와 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈 생성
    전역 변수의 억제와 캡슐화 구현 가능
    캡슐화 : 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용(= 정보 은닉)

    var Counter = (function () {
       //private 변수
       var num = 0;
    
       //외부 공개
       return {
           increase() {
               return ++num;
           },
           decrease() {
               return --num;
           }
       };
    }());
  • ES6 모듈
    파일 자체의 독자적 모듈 스코프 제공


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

  • var로 선언한 변수의 문제점
    1. 변수 중복 선언 가능
    2. 함수 레벨 스코프
    3. 변수 호이스팅

  • let 키워드
    1. 변수 중복 선언 금지
    2. 블록 레벨 스코프
    모든 코드 블록을 지역 스코프로 인정
    3. 변수 호이스팅
    선언 단계와 초기화 단계 분리 진행
    런타임 이전에 선언 단계가 진행되지만 초기화 단계는 변수 선언문에 도달했을 때 실행됨
    초기화 단계 이전에 참조하면 참조 에러 발생
    일시적 사각지대 : 스코프 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간
    변수 호이스팅이 발생하나 발생하지 않는 것처럼 동작

  • const 키워드
    1. 선언과 초기화
    선언과 동시에 초기화 해야 함
    블록 레벨 스코프, 변수 호이스팅이 발생하지 않는 것처럼 동작
    2. 재할당 금지
    3. 상수
    상수 표현할 때 const 많이 사용
    const로 선언된 변수에 객체 할당 시 값 변경 가능

  • var vs let vs const
    기본적으로 const를 사용하고 재할당이 필요한 경우에 let을 최대한 좁은 스코프로 만든다. var는 사용하지 않는다.


Ch16. 프로퍼티 어트리뷰트

  • 내부 슬롯과 내부 메소드
    js 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사양에서 사용하는 의사 프로퍼티와 의사 메로드.
    직접 호출하거나 접근하는 방법 제공 X
    but, 일부 메소드에 한 해 간접적으로 접근 가능

  • 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체
    프로퍼티 어트리뷰트(= 상태) : 값, 값의 갱신 가능 여부, 열거 가능 여부, 재정의 가능 여부
    프로퍼티 디스크립터 : 프로퍼티 어트리뷰트 정보 제공
    Object.getOwnPropertyDescriptor 메소드를 사용하면 프로퍼티 디스크립터 객체 반환

  • 데이터 프로퍼티와 접근자 프로퍼티
    데이터 프로퍼티 : 키와 값으로 구성된 일반적인 프로퍼티
    데이터 프로퍼티가 갖는 어트리뷰트: value, writable, enumerable, configurable
    접근자 프로퍼티 : 자체적으로 값을 가지지 않고 접근자 함수로 구성된 프로퍼티
    접근자 프로퍼티가 갖는 어트리뷰트: get, setenumerable, configurable
    <구분 방법>
    일반 객체의 __proto__는 접근자 프로퍼티
    함수 객체의 prototype은 데이터 프로퍼티

  • 프로퍼티 정의
    Object.defineProperty, Object.defineProperties 메서드로 프로퍼티 정의 가능
    이때 일부 프로퍼티 생략하고 정의하면 자동으로 undefined/false로 적용됨

  • 객체 변경 방지
    1. 객체 확장 방지 Object.preventExtension
    프로퍼티 추가 금지(동적 추가, Object.defineProperty 추가 둘 다)
    Object.isExtensible로 확장 가능 여부 파악

    2. 객체 밀봉 Object.seal
    읽기와 쓰기만 가능
    Object.isSealed로 밀봉 여부 파악

    3. 객체 동결 Object.freeze
    읽기만 가능
    Object.isFrozen로 동결 여부 파악

    const person = {
       name: 'Lee',
       address: {city: seoul} //얘는 동결 못함
    };

    중첩 객체까지 동결시키진 못함
    재귀적으로 모든 프로퍼티에 대해 Object.freeze 메소드 호출 필요


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

  • Object 생성자 함수
    new Object()로 빈 객체 생성 이후 프로퍼티/메소드 추가로 완성
    Object 이외에도 String, Number, Boolean, Function, Array, RegExp, Date가 있음

  • 생성자 함수
    객체 리터럴에 의한 객체 생성의 문제: 구조는 같고 값만 다른데도 계속 처음부터 만들어야한다.
    생성자 함수에 의한 객체 생성의 장점: 생성자 함수를 템플릿처럼 사용하여 구조가 동일한 객체를 여러 개 만들 수 있다.

    //객체 리터럴로 생성
    const circle = {
    	radius: 5,
       getDiameter() { return 2*this.radius }
    };
    
    //생성자 함수로 생성
    function Circle(radius) {
    	this.radius = radius;
       this.getDiameter = function () { return 2*radius };
    }

    this
    자기 참조 변수, 호출 방식에 따라 동적으로 결정됨
    일반함수 - 전역 객체
    메소드 - 메소드를 호출한 객체
    생성자 함수 - 생성자가 미래에 생성할 인스턴스

    new 연산자와 함께 호출 시 생성자 함수로 동작

  • 생성자 함수의 인스턴스 생성 과정
    new 연산자와 생성자 함수 호출 시 js엔진이 암묵적으로 인스턴스를 생성/초기화/반환 함
    <인스턴스 생성과 this 바인딩>
    암묵적으로 빈 객체가 생성되고 이 빈 객체가 인스턴스가 됨 → this에 인스턴스(빈 객체)가 바인딩됨

    바인딩
    식별자와 값을 연결하는 과정

  • 내부 메서드 [[Call]], [[Construct]]
    함수는 객체이나 일반 객체와 달리 호출 가능
    함수가 일반 함수로 호출되면 [[Call]] 호출
    함수가 new 연산자와 함께 생성자로 호출되면 [[Constructor]] 호출
    모든 함수는 callable이지만 모든 함수가 constructor인 것은 아님

    <구분>
    constructor: 함수 선언문, 함수 표현식, 클래스
    non-constructor: 메서드, 화살표 함수

  • new 연산자
    new연산자와 함께 constructor 호출 시 생성자 함수로 동작
    생성자 함수로 호출되면 new.target이 자기자신을 가리킴
    ES6부턴 스코프 세이프 생성자 패턴 사용 가능

profile
가장 높이 빛난 별 잡아보일게

0개의 댓글