함수 직접 호출과 new를 통한 호출

Min·2021년 1월 7일
0

JavaScript

목록 보기
14/18
post-thumbnail
function Person(){} 
var person = Person() 
var person = new Person() 

생성자 함수

JavaScript에서 함수는 반복되는 로직을 모아놓은 함수가 될 수도, 인스턴스의 모양(속성이나 메서드)이 정의된 생성자가 될 수도 있다. 다른 언어에서는 class와 생성자가 구분되지만, JavaScript에서는 ES6문법 이후 추가된 class 이외에 생성자 함수도 class의 역할을 한다.

function Wizard(name, hair) {
    this.name = name; 
    this.hair = hair;
    this.sayHello = function() {
    	return `안녕, 내 이름은 ${this.name}야!`;
    }
    
}
    
let harry = new Wizard('Harry Potter', 'black');
let ron = new Wizard('Ron Weasley', 'red');

harry.name; // 'Harry Potter'
harry.hair; // 'black'
harry.sayHello(); // 안녕, 내 이름은 Harry Potter야!
ron.name; // 'Ron Weasley'
ron.hair; // 'red'
ron.sayHello(); // 안녕, 내 이름은 Ron Weasley야!

위의 Wizard는 생성자 함수이다.
객체를 만들기 위한 목적의 생성자 함수는, 일반적인 함수와 구분하기 위해 첫 글자를 대문자로 쓰는 것이 관례이다.

새 인스턴스를 만들 때는 new 연산자를 사용한다. new 연산자와 함께 호출한 함수는 생성자처럼 동작하며, 내부적으로
아래와 같은 과정을 거친다.


출처 링크

  1. 생성자 함수의 코드가 실행되기 전에 비어 있는 새 객체가 생성된다.
  2. 생성자 내부에서 사용하는 this 값에 새 빈 객체 할당한다.
  3. 새 객체의 [[Prototype]]은 자신을 생성한 함수의 prototype 프로퍼티를 참조한다.
  4. 실행된 생성자 함수 내부 코드에서 this를 사용하여 앞의 빈 객체에 동적으로 프로퍼티, 메서드 (name, hiar 등)를 추가한다.
  5. 특별하게 return문이 없을 경우, this로 바인딩 된 새 객체 반환한다.
function Wizard() {}; 

let ron = Wizard();      // ron은 undefined 
let harry = new Wizard();  // harry는 Object 

Wizard는 속성과 메서드가 정의되지 않은 텅 빈 함수이기에 반환(return)값도 없다. 그러나 new 연산자와 함께 호출하면 호출된 함수의 prototype을 참조하는 새로운 객체가 반환된다. 따라서 harry는 이러한 구조를 가진다.

harry = {
    __proto__ : {
        constructor : function Wizard () {},
        __proto__ : Object
    }
}

Method의 정의

new연산자는 생성자의 this가 새로운 인스턴스를 가리키게 하고, this로 참조하는 인스턴스에 속성과 메서드를 추가한다. 그리고 그 속성과 메서드의 정의는 생성자 함수의 안에서도, 바깥에서도 모두 가능하다.

가만히 살펴보면 name(속성)은 인스턴스마다 전부 달라서('Harry Potter', 'Ron Weasley') 인스턴스에 추가되는 것이 맞지만, sayHello(메서드)는 한 공간에 한 번만 정의하고, 모든 인스턴스에서 그 공간을 참조할 수 있게 하는 방법이 더 효율적이다.

아래와 같이 Wizard.prototype 객체에 메서드를 추가하면 모든 인스턴스에서 이 메서드를 공유할 수 있다.

function Wizard(name, hair) {
    this.name = name; 
    this.hair = hair;
    }
    
 Wizard.prototype.sayHello = function() { 
   	return `안녕, 내 이름은 ${this.name}야!`;
} 
    
let harry = new Wizard('Harry Potter', 'black');
let ron = new Wizard('Ron Weasley', 'red');

harry.name; // 'Harry Potter'
harry.hair; // 'black'
harry.sayHello(); // 안녕, 내 이름은 Harry Potter야!
ron.name; // 'Ron Weasley'
ron.hair; // 'red'
ron.sayHello(); // 안녕, 내 이름은 Ron Weasley야!

매번 새로운 객체(execution context)를 생성

function Wizard(name, hair) {
    this.name = name; 
    this.hair = hair;
}
    
let harry = new Wizard('Harry Potter', 'black');
let potter = new Wizard('Harry Potter', 'black');

console.log(harry === potter ? true : false) //false

harry와 potter는 생성될 때 동일한 인자가 주어졌으므로 꼭 같은 객체일 것만 같다. 하지만 blooen 형태로 찍어보면 서로 다른 독립된 객체임을 알 수 있다. new 를 통한 생성자 함수 호출은 매번 새로운 객체(execution context)를 생성시키기 때문이다.

참고 자료
[ 생활코딩 ] 생성자와 new
자바스크립트의 함수 호출 이해하기 - web,web,web
'new' 연산자와 생성자 함수
자바스크립트 function 의 비밀(#1) - prototype 과 new
자바스크립트 함수(Function)와 함수의 call() 메소드
[스터디_자바스크립트] 15. 함수 호출과 this
this | PoiemaWeb
소년코딩의 자바스크립트 강좌 20. 생성자 함수
🙈[JS] 객체(Object)와 생성자 함수🐵

profile
slowly but surely

0개의 댓글