ES6의 함수

beomjin_97·2022년 2월 8일
0

javascript

목록 보기
4/13

1. 함수의 구분

S6에서의 함수는 그 사용목적에 따라 세가지 종류로 명확히 구분된다.

  • 일반함수 : 함수 선언문이나 함수 표현식으로 정의한 함수로 ES6이전의 함수와 동일하다.
  • 메서드와 화살표 함수 : non-constructor라는 중요한 특징이 있다.


2. 메서드

ES6이전에는 메서드에 대한 명확한 정의없이 일반적으로 객체에 바인딩된 함수를 일컫었다.
ES6에서는 메서드 축약 표현으로 정의된 함수만을 의미한다.

const obj = {
  x: 1,

  foo() {
    return this.x;
  },

  bar: function () {
    return this.x;
  },
};
// foo는 메서드, bar는 일반함수

ES6메서드는 non-constructor이므로 prototype프로퍼티가 없으며 프로토타입도 생성하지 않는다.
ES6메서드가 아닌 함수는 내부슬롯 [[HomeObject]] 를 갖지 않기 때문에 super키워드를 사용할 수 없다.

따라서 메서드를 정의할 때 메서드 축약 표현을 사용하는 것이 바람직하다.

2.1 메서드 동적 추가

ES6 메서드를 동적 추가하려면 객체 리터럴을 바인딩하고 프로토타입의 constructor 프로퍼티와 생성자 함수 간의 연결을 재설정한다.

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

Person.prototype.sayHi = function () {
  console.log(`Hi ${this.name}`);
};

Person.prototype = {
  constructor: Person,
  sayHi() {
    console.log(`Hi ${this.name}`);
  },
};

일반함수를 할당하는 위 방식 보다는 ES6 메서드를 할당하는 아래 방식이 바람직하다.



3. 화살표 함수

3.1 정의

함수 선언문이 아닌 표현식으로만 정의할 수 있다.

const multiply = (x, y) => x * y;
multiply(2,3);
  • 매개변수가 한개인 경우 ( ) 생략가능
  • 함수 몸체가 하나의 문인 경우 { } 생략가능 (표현식이 아닌 문인 경우에는 생략 불가능)
  • 객체 리터럴을 반환하는 경우 ( )로 감싸주어야 한다.
  • 즉시 실행문으로 사용가능하다.
const power = x => x ** 2;

const create = (id, content) => ({ id, content });
// const create = (id, content) => { return { id, content }; }; 와 같다.

const person = ((name) => ({
  sayHi() {
    return `Hi My name is ${name}`;
  },
}))("Lee");

console.log(person.sayHi());

3.2 일반 함수와의 차이

  • non-constructor이다.
  • 중복된 매개변수이름을 선언할 수 없다.
  • 자체의 this, arguments, super, new.target 바인딩을 갖지 않는다.

3.3 this

this 바인딩은 함수를 정의 할 때 정해지는 것이 아니라 함수의 호출 방식에 따라 동적으로 결정된다. 일반함수를 콜백함수로 사용하는 경우 콜백함수와 일반함수의 this가 서로 다른 값을 가리킬 수 있다.

class Prefixer {
  constructor(prefix) {
    this.prefix = prefix;
  }

  add(arr) {
    return arr.map(function (item) {  
      return this.prefix + item;    // 일반함수의 this는 strict mode에서 undefined 이다.
    });
  }
}

const prefixer = new Prefixer('-webkit-');
console.log(prefixer.add(['transition', 'user-select']))

이와 같은 문제를 해결하기 위해 화살표 함수를 사용할 수 있다. 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 참조한다.

class Prefixer {
  constructor(prefix) {
    this.prefix = prefix;
  }

  add(arr) {
    return arr.map((item) => this.prefix + item);
  }
}

const prefixer = new Prefixer("-webkit-");
console.log(prefixer.add(["transition", "user-select"]));

화살표함수가 중첩되어 있으면 화살표 함수가 아닌 가장 가까운 상위 함수를 찾는다.
화살표 함수는 자체의 this 바인딩을 가지지 않으므로 call, apply, bind 메서드를 사용해도 this를 교체할 수 없다.

this가 전역 객체로 가리키기 때문에 메서드를 화살표 함수로 정의하는 것은 피해야 한다. 메서드 축약 표현을 사용하는 것이 바람직하다.

3.4 super

this와 마찬가지로 화살표 함수 내부에서 this를 참조하면 상위 스코프의 super을 참조한다.

class Base {
  constructor(name) {
    this.name = name;
  }

  sayHi() {
    return `Hi ${this.name}`;
  }
}

class Derived extends Base {
  sayHi = () => `${super.sayHi()}`;  // consturctor의 super을 참조한다.
}

3.5 arguments

this와 마찬가지로 화살표 함수 내부에서 this를 참조하면 상위 스코프의 arguments을 참조한다.

(function () {
  const foo = () => console.log(arguments); 
  foo(3, 4);
})(1, 2);

// [1, 2] , 외부함수인 즉시실행함수의 arguments를 가리킨다.

4. Rest 파라미터

Rest 파라미터는 함수에 전달된 인수들을 목록을 배열로 전달 받는다.

function foo(...rest) {
  console.log(rest);
}

foo(1, 2, 3, 4, 5);  // [1, 2, 3, 4, 5]

일반 매개변수와 함께 사용할 수 있다. 단 Rest 파라미터는 할당된 인수를 제외한 나머지 인수이므로 반드시 마지막 파라미터이어야 한다.

function foo(x, y, ...rest) {
  console.log(x);  // 1
  console.log(y);  // 2
  console.log(rest);  // [3, 4, 5]
}

foo(1, 2, 3, 4, 5);

함수의 arguments 객체는 배열이 아닌 유사 배열 객체이다. 대신 rest 파라미터를 사용하면 배열을 직접 얻을 수 있다.

function sum(...args) {
  return args.reduce((pre, cur) => pre + cur, 0);
}

console.log(sum(1, 2, 3, 4, 5));  // 15

화살표함수는 함수 자체의 arguments 객체를 갖지 않기 때문에 반드시 rest파라미터를 사용해야 한다.



5. 매개변수 기본값

ES6에서 도입된 매개변수 기본값

function sum(x = 0, y = 0) {
  return x + y;
}

console.log(sum(1));  // 1
console.log(sum(1, 2));  // 3
  • 기본값은 매개변수에 인수를 전달하지 않는 경우와 undefined를 전달한 경우에만 유효하다.
  • rest파라미터에는 기본값을 지정할 수 없다.
  • 함수 객체의 length 프로퍼티와, arguments 객체에는 전혀 영향을 주지 않는다.
profile
Rather be dead than cool.

0개의 댓글