모던 자바스크립트-Deep Dive 17,18 [생성자 함수에 의한 객체 생성,함수와 일급 객체]

Gavri·2022년 3월 23일
0

DeepDive

목록 보기
9/12

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

Object 생성자 함수

js는 Object 생성자 함수 이외에도 String,Number,Boolean,Function, Array, Date, RegExp, Promise등의 빌트인 생성자 함수를 지원한다.
사용법 : const person = new Object();

생성자 함수

객체 리터럴로 생성시 문제점

똑같은 여러 객체를 만들경우 코드가 중복되며 비효율적이다.

const circle1 = {
  radius:5,
  getDiameter(){
    return 2 * this.radius
  }
}
const circle2 = {
  radius:10,
  getDiameter(){
    return 2 * this.radius
  }
}

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

function Circle(radius) {
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}
const circle1 = new Circle(5);
const circle2 = new Circle(10);
//	프로퍼티구조가 동일한 객체를 여러 개 생성할 경우 편리하다.

this

this는 객체 자신의 프로퍼티나 메서드를 참조하기 위한 자기 참조 변수이다.

함수 호출 방식this가 가리키는 값(바인딩)
일반 함수로 호출전역객체
메서드로서 호출메서드를 호출한 객체
생성자 함수로서 호출생성자 함수가 생성할 인스턴스

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

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

암묵적으로 빈 객체(생성자 함수가 생성한 인스턴스)가 생성되고 this에 바인딩된다.
이 처리는 런타임 이전에 실행된다.

바인딩
바인딩이란 식별자와 값을 연결하는 과정을 의미한다. 예를 들어, 변수 선언은 변수 이름과 확보된 메모리 공간의 주소를 바인딩 하는 것이다. this 바인딩은 this와 this가 가르킬 객체를 바인딩하는 것이다.

function Circle(radius){
  console.log(this); // Circle ()
  ...
}

2. 인스턴스 초기화

생성자 함수에 기술되어 있는 코드가 한 줄씩 실행되어 this에 바인딩되어 있는 인스턴스를 초기화한다.즉,
this에 바인딩되어 있는 인스턴스에 프로퍼티나 메서드를 추가하고 생성자 함수가 인수로 전달받은 초기값을 인스턴스 프로퍼티에 할당하여 초기화하거나 고정값을 할당한다.

3. 인스턴스 반환

function Circle(radius) {
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
  return this; // 		1.암묵적으로 this 가 리턴된다 
  return {}; // 		2.객체를 반환하는 경우 암묵적 this반환이 무시된다
  return 100; // 		3.원시값을 반환할 경우 무시되고 this가 반환된다.
}
console.log(new Circle(5));
//	1. Circle { radius: 5, getDiameter: [Function (anonymous)] }
//	2. {}
//	3. Circle { radius: 5, getDiameter: [Function (anonymous)] }

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

js의 경우 함수 또한 객체로 인식되어 프로퍼티 소유, 메서드 또한 소유할 수 있다.
일반 객체와 다른 점은 호출이 가능하다는 것이다.

function foo() {}
//	일반적인 함수로서 호출 : [[Call]]이 호출된다
foo()
//	생성자 함수로서 호출 : [[Construct]]이 호출된다
new foo();

내부 메서드[[Call]]을 갖는 함수 객체 = callable
내부 메서드[[Construct]]를 갖는 함수 객체 = constructor
내부 메서드[[Construct]]를 갖지않는 함수 객체 = non-constructor
함수 객체의 경우 반드시 callable 이여야 한다.

constructor, non-constructor 구분

constructor : 함수 선언문, 함수 표현식 , 클래스
non-constructor : 메서드(ES6 메서드 축약 표현), 화살표 함수

//	constructor
function foo(){}
const bar = function () {};
const baz = {
  x:function () {}
};

// 	non-constructor
const arrow = () => {}
const person = {
  name:"Lee",
  getName(){
    return this.name
  }
}
new arrow() // TypeError
new person.getName() // TypeError

new 연산자, new.target

new 연산자의 경우 [[Construct]] 가 호출되기에 constructor 이여야 한다.

new 없이 함수를 호출할경우 [[Call]]이 호출된다. 생성자 함수가 new 연산자 없이 호출되는 것을 방지하기 위해 파스칼 케이스 컨벤션을 이용하나 실수는 언제든 발생할 수 있다. 이러한 위험성을 피하기 위해 new.target을 지원한다.(ES6)

function Circle(radius) {
  if(!new.target){ // 함수가 new 연산자와 함께 호출되지 않으면 new.target은 undefined을 반환한다.
    return new Circle(radius);
  }
  ...
}
  const circle = Circle(5); == new Circle(5)
  

함수와 일급 객체

일급 객체

다음 조건을 만족하는 객체를 일급 객체라 한다
1. 무명의 리터럴로 생성 가능하다. 즉 런타임에 생성이 가능하다
2. 변수나 자료구조에 저장할 수 있다.
3. 함수의 매개변수에 전달할 수 있다.
4. 함수의 반환값으로 사용할 수 있다.

함수 객체의 프로퍼티


function square(number) {
  return number * number;
}
console.dir(Object.getOwnPropertyDescriptors(square));

{
  length: { value: 1, writable: false, enumerable: false, configurable: true },
  name: {    value: 'square',    writable: false,    enumerable: false,    configurable: true  },
  arguments: {    value: null,    writable: false,    enumerable: false,    configurable: false  },
  caller: {    value: null,    writable: false,    enumerable: false,    configurable: false  },
  prototype: { value: {}, writable: true, enumerable: false, configurable: false }
}

arguments,caller,length,name,prototype 프로퍼티는 모두 함수 객체의 데이터 프로퍼티이다.
이들 프로퍼티는 일반 객체에는 없는 함수 객체 고유의 프로퍼티다.
__proto__의 경우 접근자 프로퍼티 이며 함수 객체 고유의 프로퍼티가 아닌 Object.prototype 객체의 프로퍼티를 상속 받은 것이다.

argument 프로퍼티🎁

함수 객체의 argument 프로퍼티 값은 argument 객체이다.
argument객체는 함수 호출 시 전달된 인수들의 정보를 담고 순회가능한 유사 배열 객체이며, 함수 내부에서 지역 변수처럼 사용된다.

function sum() {
  let res = 0;
  for (const item of arguments) {
    // arguments 객체는 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 때 유용하다.
    res += item;
  }
  return res;
}
console.log(sum());
console.log(sum(1));
console.log(sum(1, 2));
console.log(sum(1, 2, 3));

// 0
// 1
// 3
// 6

length 프로퍼티

함수를 정의할 때 선언한 매개변수의 개수를 가리킨다.

name 프로퍼티

ES6 이전에는 빈 문자열의 값을 반환한다
ES6 부터는 함수 이름을 반환한다.

var namedFunc = function foo() {};
console.log(namedFunc.name);

var namedFunc1 = function () {};
console.log(namedFunc1.name);

function bar() {}
console.log(bar.name);

//  foo
//  namedFunc1
//  bar

prototype 프로퍼티

생성자 함수로 호출할 수 있는 객체,즉 constructor만이 소유하는 프로퍼티이다.

profile
모든건 기록으로

0개의 댓글