ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2021_12_14 생성자 함수에의한 객체 생성
    IT/js 2021. 12. 14. 19:12

    딥다이브 생성자 함수에 의한 객체 생성 17장 정리

     

      - 10객체 리터럴에서 객체 리터럴에 의한 객체 생성 방식을 살펴보았음

     

      - 객체 리터럴에 의한 객체 생성 방식은 가장 일반적이고 간단한 객체 생성 방식

      - 다양한 방법으로 생성할 수 있음

     

      - 17장에서는 여러 생성방식 중 생성자 함수를 사용하여 객체 생성 방식 설명

      - 정리하자면 객체리터럴 vs 생성자 함수 사용 장단점 비교하는 장이 되겠다.

     

    1. Object 생성자 함수

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

      - 빈 객체를 생성한 이후 프로퍼티 또는 메서드를 추가하여 객체를 완성할 수 있다.

    const person = new Object();
    
    person.name = 'Lee'
    person.sayhello = function(){
    	console.log('Hello My name + this.name);
    }
    
    console.log(person); // {name: "Lee", sayHello: f}
    person.sayhello(); // Hello My name Lee

      1.1. 예제를 살펴보자면 person이라는 이름을 가진 생성자 Object 객체를 생성

      1.2. name이라는 메서드에 문자열을 담을 수 있음

      1.3. sayhello 라는 메서드에 함수를 담을 수 있음

        1.3.1. sayhello 함수 내부에 this를 사용하여 person의 name을 가지고올 수 있음

      1.4. person을 출력 시 메서드를 출력

      1.5. person.sayhello() 메서드 함수 출력 시 함수 결과값 출력

     

      - Object 생성자 함수 외에도 String, Number, Boolean, Function, Array, Data, RegExp, Promise 등의 빌트인 생성자 함수를 제공 (RegExp - 정규표현식)

      - Object 생성자 함수는 빈 객체 생성하는 것임

     

    2. 생성자 함수

      - 객체 리터럴에 의한 생성 방식은 직관적이고 간편

      - but 객체 리터럴에 의한 객체 생성 방식은 단 하나의 객체만 생성

      - 따라서 동일한 프로퍼티를 갖는 객체를 여러 개 생성해야 할 경우 매번 같은 프로퍼티 기술 해야해서 비효율

    const circle1 = {
    	radius:5,
    	getDiamter(){
    		return 2 * this.radius;
    	}
    };
    
    console.log(circle1.getDiameter()); // 10
    
    const circle2 = {
    	radius:10,
    	getDiamter(){
    		return 2 * this.radius;
    	}
    };
    
    console.log(circle2.getDiameter()); // 20

      - 프로퍼티는 객체마다 값이 다를 수 있지만 메서드 내용이 동일한 경우가 일반적

      - 위 예제의 circle1 객체와 circle2 객체는 프로퍼티 구조가 동일함

      - radius 프로퍼티의 값은 객체마다 다를 수 있지만 getDiameter 메서드는 완전히 동일하다.

      - 한 두개라면 문제가 안되겠지만 수십 개의 객체를 만들경우 객체 리터럴에 의한 객체 생성은 문제가 크다~

     

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

      - 생성자 함수에 의한 객체 생성방식은 객체를 생성하기 위한 템플릿(클래스) 처럼 생성자 함수를 사용하여 프로퍼티 구조가 동일한 객체 여러 개를 간편하게 생성 -> 인자로 데이터 값 넣으면 재활용 할 수 있으니 쉽다

      - 정리하자면

      3.1. 함수하나 만들기

      3.2. 함수인자값에 다른데이터 넣고 new 를 붙여서 변수안에 넣기

      3.3. 객체를 손쉽게 재활용 가능

     

      - 당연하게도 new 연산자와 함께 생성자 함수를 호출하지 않으면 일반 함수로 작동

     

    4. 생성자 함수 인스턴스 생성 과정

      - 생성자 함수 몸체에서 수행해야 하는 것이 무엇인지 생각

      - 생성자 함수의 역할은 프로퍼티 구조가 동일한 인스턴스 생성, 생성된 인스턴스를 초기화 및 할당

      - 인스턴스 생성은 필수, 인스턴스 초기화는 옵션

      - js 엔진은 new 연산자와 함께 함수를 호출하면 암묵적인 처리로 인스턴스 생성하고 초기화 후 반환

     

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

      - 암묵적으로 빈 객체가 생성 -> 생성자 함수가 생성한 인스턴스

      - 생성된 빈 객체(인스턴스)는 this에 바인딩

      - 생성자 함수 내부에 this가 생성자 함수가 생성할 인스턴스를 가르키는 이유가 이것임

      - 런타임 이전에 실행되는 것

      * 바인딩은 this가 가르칠 객체의 메모리 공간을 미리 잡고 연결 해주는 것 (런타임 이전 실행)

     

    4.2. 인스턴스 초기화

      - this 바인딩도 암묵적으로 처리가 된다. 

      - 정리하면 원래는 this 바인딩을 하고 생성해야할 인스턴스 주소값을 확보한 다음 내가 초기화하고 할당 다해야하는데

      - js에서 암묵적으로 this 바인딩을 해주니깐 나는 바로 인스턴스 초기화하고 값할당 하고 하기만 하면된다.

     

    4.3. 인스턴스 반환

      - 암묵적으로 this가 바인딩되고 작업한 것 조차도 메모리에 잡히기 때문에

      - new 를 붙여서 생성자 함수로 만들면 this가 유유히 사라진다. (데이터도 반환)

      - 하지만 return 값을 넣으면 this가 열심히 잡아놓은 공간을 무시하고 return 값이 반환된다.

         ( 함수 내부 내용을 넣어봤자 return 넣어서 날려버릴 수 있다 단, 원시값 넣으면 다시 this 반환함 )

      - 결론은 생성자 함수 사용했으면 어지간해선 return문 생략하자

     

    5. 내부 메서드 call, construct

      - 함수 선언문 또는 함수 표현식으로 정의한 함수는 일반적인 함수로서 호출할 수 있는것은 물론 생성자 함수로도 호출할 수 있음

      - 물론 생성자 함수는 new 연산자와 함께 호출

      - 함수는 객체이므로 일반 객체와 동일하게 동작할 수 있음

      - 함수 객체 = 일반 객체 (내부 슬롯, 내부 메서드)

      - 그냥 한마디로 일반 함수도 내부 메서드로 호출해서 잘 사용할 수 있다.

      - 차이점은 일반 함수면 Call, new 넣은 생성자 함수면 Construct가 호출된다.

      

      - 모든 함수는 callable을 가지고 있음

      - 생성자 함수는 Construct를 가지고 있음

      - 따라서 모든 함수는 Construct, non-Construct 로 나뉜다.

      - 즉 모든 함수는 객체를 호출 할 수 있지만 생성자와 그냥 함수로 나뉜다.

     

     

    6. Construct, non-Construct 구분

      - Construct : 함수 선언문, 함수 표현식, 클래스

      - non-Construct : 메서드, 화살표 함수, function이 없는 축약문(메서드가 된다.)

      - 고로 non-Construct 는 생성자 함수로 호출하면 에러 발생

     

    7. new 연산자

      - 일반 함수와 생성자 함수는 특별한 형식적 차이는 없음 new 붙이면 생성자 함수로 동작할뿐

      - 생성자 함수는 return을 쓰더라도 { } 감싸주자 그래야 호출된다.

      - 일반 함수의 this는 함수 내부가 아닌 전역 window를 가리킨다.

      - 표기에 별 차이가 없기 때문에 그래서 생성자 함수는 보통 첫 문자를 대문자로 기술한다.

     

    8. new.target

      - 생성자 함수가 new 연산자 없이 호출될 수 있으니 ES6 에서 new.target 지원

      - 메타 프로퍼티라 불리고 IE는 지원하지 않는다..

      - 함수 내부에서 new.target 사용하면 new 연산자와 함께 생성자 함수로 호출되었는지 확인 할 수 있다.

      - new 연산자랑 new.target 같이 사용하면 new.target은 함수 자신을 가르킨다. 

      - 만약 new가 없는데 new.target 사용하면 undefined 나온다.

      - 그러므로 new가 있는지 없는지 판별가능

      - 실수로 new를 빼먹었어도 new.target이 있으면 생성자 함수로서 호출되기는 한다. (거진 예외처리)

     

      - IE에서 안되니깐 다른 문법으로는 

      - 아래 방식으로 예외처리를 진행 할 수 있다. ( new.target도 함수를 가르키니, this로 판별 가능)

    function Circle(radius){
    	if(!(this instanceof Circle){
        	return new Circle(radius);
        }
    }

       - instanceof 연산자는 19장 프로토타입에서 살펴볼 것

     

    9. 마무리

       - 대부분의 빌트인 생성자 함수 String, Number, Boolean, Function, Array, Data, RegExp, Promise 등 생성자 함수는 new가 잇냐 없냐에 따라 적절한 값을 반환한다

      - Object는 new가 있건 없건 동일하게 작동하니 어지간해선 쓰지말자.

      - Object가 아닌 생성자 함수를 사용할땐 반드시 new의 유무를 확인하거나 예외처리를 진행하자

     

    let obj = new Object();
    console.log(obj); // {}
    
    obj = Object();
    console.log(obj); // {}
    
    ---------------------------
    
    const str = String(123);
    console.log(str, typeof str); // 123 string
    
    const str = new String(123);
    console.log(str, typeof str); // String{'123'} 'object'
    
    const num = Number('123');
    console.log(num, typeof num); // 123 'number'
    
    const num = new Number('123');
    console.log(num, typeof num); // Number {123} 'object'

     

     

Designed by Tistory.