본문 바로가기
Front-End/JavaScript

17장 생성자 함수에 의한 객체 생성 20장 strict mode 22장 this (모던 자바스크립트 Deep Dive)

by kk님 2023. 4. 28.

모던 자바스크립트 Deep Dive 글 목록(스터디)
https://hello-kk.tistory.com/780


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

function Circle(radius){
    this.radius = radius;
    this.getDiameter = function(){
        return 2*this.radius;
    }
}
new Circle(5) Circle(5)
인스턴스 생성
반지름이 5인 Circle 객체 생성
함수 호출
return이 없다면 undefined 반환
this: 생성자 함수가 생성할 인스턴스 this: 전역 객체

함수는 객체이지만, 호출 가능

 [[Call]] : 호출할 수 있는 객체 == 함수

 [[Construct]] : 생성자 함수로서 호출할 수 있는 함수

 

this 바인딩이 불일치하는 이유: 자바스크립트 엔진에 의해 평가가 이루어지고(렉시컬 스코프, 함수 객체 생성), 실행(호출)은 추후에 이루어지기 때문

Function.prototype.apply/call/bind 메서드에 의한 간접 호출

apply call bind
함수를 호출
첫번째 인수를 this에 바인딩
함수를 호출
첫번째 인수를 this에 바인딩
함수 호출 X
첫번째 인수를 this 바인딩이 교체된 함수를 새롭게 생성해 반환.
즉, 명시적 호출 추가 필요

내부 중첩 함수, 콜백 함수의 this가 불일치하는 문제 해결
인수를 배열로 묶어 전달
getThisBinding.call(thisArg, [1,2,3])
인수를 쉼표로 구분해 전달
getThisBinding.call(thisArg, 1,2,3)
callbackFunc.bind(this)

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

이번 장 목표

1. 생성자 함수를 사용한 객체 생성 방식

2. 장단점: 객체 리터럴 vs 생성자 함수

 

17.1 Object 생성자 함수

const person = new Object()

빌트인 생성자 함수 종류

String Number Boolean Function Array Date RegExp Promise

new 연산자 없이 호출했을 때,

new 연산자와 함께 호출했을 때와 동일하게 동작 값 반환(= 타입 변환)
Object Function      
    String Number Boolean

17.2 Object 생성자 함수

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

객체 리터럴 방식: 동일한 프로퍼티를 갖는 객체를 여러개 생성해야하는 경우 비효율적

 

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

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

 

1. 함수와 동일한 방법으로 정의

2.  new연산자와 함께 호출

new가 없다면? => 일반 함수로 동작

 

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

생성자 함수의 역할

● 인스턴스 생성

● 인스턴스 초기화

 

자바스크립트 엔진은, 

1. 인스턴스 생성과 this 바인딩: 런타임 이전에 실행

    ○ 암묵적 빈 객체 생성(인스턴스)

     인스턴스에 this 바인딩

2. 인스턴스 초기화: 개발자가 기술함

     this에 바인딩 된 인스턴스에 프로퍼티, 메서드 추가 및 값 할당

3. 인스턴스 반환

     모든 처리 이후, 완성된 인스턴스는 바인딩된 this를 암묵적으로 반환

    ↔ 만약 return으로 다른 객체를 반환하는 경우, 명시된 객체가 반환됨

    ↔ 하지만, return으로 원시값(예: 100)을 반환하는 경우, this가 반환

 

∴ return 문 반드시 생략!

 

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

함수는 객체이지만, 호출 가능

 [[Call]] : 호출할 수 있는 객체 == 함수

 [[Construct]] : 생성자 함수로서 호출할 수 있는 함수

 

함수는 constructor일 수도, non-constructor일 수도 있다

 

17.2.5 constructor와 non-constructor의 구분

자바스크립트 엔진

● constructor: 함수, 선언문, 함수 표현식, 클래스

● non-constructor: 메서드( 축약 표현), 화살표 함수

 

17.2.6 new 연산자

● new 연산자 사용해서 생성자 함수 호출

[[Construct]] 호출. ([[Call]] 호출)

new 연산자 없이 생성자 함수 호출=> 일반 함수

[[Call]] 호출. ([[Construct]] 호출)

=> 이 경우, this.프로퍼티는 전역 객체가 this를 의미하기 때문에, 한번 생성자 함수를 호출해버린 경우 모두 전역 객체의 프로퍼티로 귀속

 

17.2.7 new.target

new 연산자와 생성자 함수로서 호출했는지 여부를 검사

return으로 인스턴스 생성 후 반환

 

22장 this

22.1 this 키워드

객체 리터럴은 circle 변수에 할당되기 직전에 평가됨.

따라서, 호출 시점에서는 이미 객체가 생성된 상태

 

생성자 함수를 정의하는 시점에는 인스턴스가 생성되기 전임.

그렇기 때문에 생성할 인스턴스를 가리키는 식별자를 알 수 없음.

=> this는 자기 참조 변수

자바스크립트 엔진에 의해 암묵적으로 생성됨

 

this 바인딩은 동적으로 결정됨

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

함수 호출 방식

일반 함수 호출

메서드 호출

● 생성자 함수 호출

● Function.prototype.apply/call/bind 메서드에 의한 간접 호출

 

22.2.1 일반 함수 호출

기본적으로 this는 전역 객체 바인딩

 

메서드 내 중첩 함수의 this: window

메서드 내의 콜백 함수의 this: window

=> 헬퍼 함수로의 역할을 다하지 못함

 

★해결방법★

 this를 바로 참조하지 말고,

  (1) cost that = this 로 참조 변수를 생성한 뒤,

  (2) that을 참조

 apply, call, bind 메서드 사용

 화살표 함수 사용

 

22.2.2 메서드 호출

호출한 객체에 바인딩

메서드를 어디에 할당하는지! 메서드를 프로퍼티로 갖게 되는게 어떤것인지

22.2.3 생성자 함수 호출

(1) new를 사용해 인스턴스를 생성한 경우

(2) 일반 함수로 호출한 경우

22.2.3 Function.prototype.apply/call/bind 메서드에 의한 간접 호출

apply call bind
함수를 호출
첫번째 인수를 this에 바인딩
함수를 호출
첫번째 인수를 this에 바인딩
함수 호출 X
첫번째 인수를 this 바인딩이 교체된 함수를 새롭게 생성해 반환.
즉, 명시적 호출 추가 필요

내부 중첩 함수, 콜백 함수의 this가 불일치하는 문제 해결
인수를 배열로 묶어 전달
getThisBinding.call(thisArg, [1,2,3])
인수를 쉼표로 구분해 전달
getThisBinding.call(thisArg, 1,2,3)
callbackFunc.bind(this)

20장 strict mode

변수 선언이 없다면, 암묵적 전역 상태가 됨

=> 엄격 모드 적용

문법적 오류, 잠재적 오류 찾아내고 오류 원인을 리포팅해줌

 

20.2 strict mode의 적용

함수 선두에 'use strict'; 추가

 

20.3 전역에 strict mode를 적용하는 것 피하기

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

=> 즉시실행 함수로 감싼 스크립트 단위로 적용

20.5 strict mode가 발생시키는 에러

20.5.1 암묵적 전역 ReferenceError

20.5.2 변수, 함수, 매개변수의 삭제 SyntaxError

20.5.3 매개변수 이름의 중복 SyntaxError

20.5.4 with 문의 사용 SyntaxError => 사용하지 않는 것이 좋다

 

20.6 strict mode 적용에 의한 변화

20.6.1 일반 함수의 this

this에 undefined 바인딩

=> 일반 함수는 this를 사용하지 않아도 되기 때문

20.6.2 arguments 객체

=> 매개변수에 전달된 인수를 재할당해서 변경해도 arguments 객체에 반영되지 않음