[우아한 테크러닝] React&TypeScript 2회차(2) - 자바스크립트의 생성자 함수 그리고 ES6 화살표 함수

minidoo·2020년 9월 5일
0

우아한 테크러닝

목록 보기
3/6

생성자 함수

생성자 함수?
여러개의 동일한 속성을 가지는 객체 생성이 가능한 함수

function User(name) {
  this.name = name;
}

let user = new User('miniddo');
console.log(user.name);  // 'miniddo'

생성자 함수와 new 연산자로 만들어진 객체를 인스턴스(instance)라고 한다.
예제에서 this.name = name은 생성자고 user은 인스턴스이다.

생성자 함수에는 두 가지 규칙이 있다.

  • 함수 이름의 첫 글자는 대문자로 표기한다.
  • new 연산자를 붙여 함수를 실행한다.

위의 예제가 작동되는 순서를 알아보자.

1. new 연산자로 빈 객체를 만들고 이를 this에 할당한다.
   this = {};  // 암묵적으로 생략되어 있다.
2. 함수를 실행하여 this에 값을 넣는다.
   this = { name: 'miniddo' };
3. this를 반환한다.
   return this;  // 암묵적으로 생략되어 있다.

이처럼 객체 생성 이후에 새로운 속성을 객체에 추가하는 것을 '동적 바인딩'이라 한다.


화살표 함수 (Arrow Function)

화살표 함수 = 애로우 함수 = 람다 함수

const arrowFunc = () => {
  return 1;
}

화살표 함수는 ES6에서 새로 나온 함수 형태로, 이름이 없어 재귀 호출이 불가능하다.
화살표 함수는 매개변수와 리턴을 표시하는 방법이 다양하다.

// 매개변수

() => {}       // 매개변수가 없을 경우
x => {}        // 매개변수가 1개인 경우 - 괄호 생략
(x, y) => {}   // 매개변수가 여러 개인 경우


// 리턴

x => x * 2         // 한 줄 함수 - 중괄호 생략, 암묵적으로 return
() => ({x : '2'})  // 객체 return은 괄호 사용, 암묵적으로 return
() => {            // 그 외 - 중괄호 사용
  return 0; 
}

화살표 함수 vs 일반 함수

화살표 함수는 class 문법을 사용하여 생성자를 명시적으로 표현한다.

class User {
  construtor(name) {  // 생성자가 명시적으로 표현
    this.name = name;
  }
}

let user = new User('miniddo');
console.log(user.name);  // 'miniddo'

화살표 함수는 constructor 함수 안에서 생성자를 명시적으로 표현한다.

화살표 함수는 this가 가리키는 값이 변하지 않는다.

일반 함수

const user = {
  name: 'miniddo',
  getName: function() {
    console.log(this);   // (A)
    setTimeout(function() {
      console.log(this);   // (B)
    }, 1000);
  }
};

user.getName();

(A) : Object {name: "miniddo", getAge: function getAge()}
⇒ 예상한대로 객체가 반환된다.
(B) : window
⇒ 여기서의 this는 전역 객체인 window를 가리킨다.
이는 생성자 함수와 객체의 메소드를 제외한 모든 함수에서의 this는 내부의 전역 객체를 가리키기 때문이다.

일반함수에서는 this의 값을 유지하기 위해 bind 함수를 사용한다.

const user = {
  name: 'miniddo',
  getName: function() {
    console.log(this);   // (A) 
    setTimeout(function() {
      console.log(this);   // (B)
    }.bind(this), 1000);   // bind 사용
  }
};

user.getName();

내부 함수를 bind 함수로 호출하면 (A)와 (B) 모두 원하는 객체 값이 반환된다.


화살표 함수

const user = {
  name: 'miniddo',
  getName: function() {
    console.log(this);   // (A) {name: "miniddo"}
    setTimeout(() => {
      console.log(this);   // (B) {name: "miniddo"}
    }, 1000);
  }
};

user.getName();

화살표 함수의 this는 클로저 함수처럼 언제나 상위 스코프의 this를 가리키기 때문에 변하지 않는다.


일반 함수는 new를 붙이지 않아도 생성자로 사용되지만, 화살표 함수는 반드시 붙여야한다.

일반 함수

let User = function(name) {
  if(!(this instanceof User)) {
    return new User(name);
  }
  this.name = name;
};

let user = User('miniddo');   // new 연산자를 붙이지 않아도 호출 가능
console.log(user);   // User {name: 'miniddo', constructor: Object}

화살표 함수 사용 시 주의할 점

let User = {
  name: 'miniddo',
  getName: () => console.log(this.name)   // undefined
};

User.getName();

화살표 함수의 this는 상위 스코프의 this를 가리킨다.
메소드로 정의한 화살표 함수의 this는 내부의 객체가 아닌 상위 스코프의 window 객체이다.
따라서 화살표 함수로 메소드 자체를 정의하는 것을 바람직하지 않은 코드이다.


클로저(Closure) 함수

클로저(Closure)?
외부 함수의 환경을 기억하고 있는 내부 함수

function outdoor() {
  let num = 10;
  
  function indoor() {
    return num;
  }
  
  return indoor();
}

console.log(outdoor());   // 10 

자바스크립트에서 함수가 선언될 때 자신이 접근할 수 있는 범위를 정하고 기억하는데 이를 '렉시컬 스코프'라고 한다.
이런 렉시컬 스코프에 의해 외부 함수의 환경을 기억하고 있는 내부 함수가 '클로저'이다.

위의 예제에서 indoor() 함수를 기준으로,
외부 함수인 outdoor()의 num 값을 내부 함수 indoor()이 기억하고 있기 때문에 10의 결과가 나온다.

0개의 댓글