ES6 함수의 추가 기능

ken6666·2024년 3월 13일
0

JS

목록 보기
22/39

함수의 구분

ES6 이전의 모든 함수는 일반 함수로서 호출할 수 있는 것은 물론 생성자 함수로서 호출할 수 있다.

ES6에서는 함수를 사용 목적에 따라 세 가지 종류로 명확히 구분한다.

메서드

const obj = {
  x: 1,
  // foo는 메서드이다.
  foo() { return this.x; },
  // bar에 바인딩된 함수는 메서드가 아닌 일반 함수이다.
  bar: function() { return this.x; }
};

console.log(obj.foo()); // 1
console.log(obj.bar()); // 1
  • ES6 사양에서 메서드는 메서드 축약 표현으로 정의된 함수만을 의미한다.
  • 정의한 메서드는 인스턴스를 생성할 수 없는 non-constructor이다.
  • 인스턴스를 생성할 수 없으므로 prototype 프로퍼티가 없고 프로토 타입을 생성하지 않는다.
  • 메서드는 자신을 바인딩한 객체를 가리키는 내부슬롯 [[HomeObject]]를 가진다. 따라서 super 키워드도 사용 가능하다.
const base = {
  name: 'Lee',
  sayHi() {
    return `Hi! ${this.name}`;
  }
};

const derived = {
  __proto__: base,
  // sayHi는 ES6 메서드다. ES6 메서드는 [[HomeObject]]를 갖는다.
  // sayHi의 [[HomeObject]]는 sayHi가 바인딩된 객체인 derived를 가리키고
  // super는 sayHi의 [[HomeObject]]의 프로토타입인 base를 가리킨다.
  sayHi() {
    return `${super.sayHi()}. how are you doing?`;
  }
};

console.log(derived.sayHi()); // Hi! Lee. how are you doing?
  • 메서드가 아닌 함수는 super 키워드를 사용할 수 없다.

화살표 함수

화살표 함수 정의

함수 정의

const multiply = (x, y) => x * y;
multiply(2, 3); // -> 6
  • 화살표 함수는 함수 선언문으로 정의할 수 없고 함수 표현식으로 정의해야 한다.

매개변수 선언

const arrow = x => { ... };
  • 매개변수가 한개인 경우 소괄호를 생략할 수 있다.
const arrow = () => { ... };
  • 매개변수가 없는 경우 소괄호를 생략할 수 없다.

함수 몸체 정의

// concise body
const power = x => x ** 2;
power(2); // -> 4

// 위 표현은 다음과 동일하다.
// block body
const power = x => { return x ** 2; };
  • 함수 몸체가 하나의 문으로 구성된다면 함수 몸체를 감싸는 중괄호 생략 가능하다.
const arrow = () => const x = 1; // SyntaxError: Unexpected token 'const'

// 위 표현은 다음과 같이 해석된다.
const arrow = () => { return const x = 1; };
  • 함수 몸체 내부의 문이 표현식이 아니라면 중괄호 생략 불가.
const create = (id, content) => ({ id, content });
create(1, 'JavaScript'); // -> {id: 1, content: "JavaScript"}

// 위 표현은 다음과 동일하다.
const create = (id, content) => { return { id, content }; };
  • 객체 리터럴을 반환하는 경우 소괄호를 감싸주어야 한다.

화살표 함수와 일반 함수의 차이

  1. 화살표 함수는 인스턴스를 생성할 수 없는 non-constructor다.
const Foo = () => {};
// 화살표 함수는 생성자 함수로서 호출할 수 없다.
new Foo(); // TypeError: Foo is not a constructor
  • 화살표 함수는 인스턴스를 생성할 수 없으므로 prototype 프로퍼티가 없고 프로토타입도 생성하지 않는다.
  1. 중복된 매개변수 이름을 선언할 수 없다.
const arrow = (a, a) => a + a;
// SyntaxError: Duplicate parameter name not allowed in this context
  • 화살표 함수에서도 중복된 매개변수 이름을 선언하면 에러를 발생한다.
  • 일반 함수(strict mode 제외) 중복된 매개변수 이름을 선언해도 에러가 발생하지 않는다.
  1. 화살표 함수는 함수 자체의 this, arguments,super,new.target 바인딩을 갖지 않는다
  • 상위 스코프의 this, arguments,super,new.target을 참조한다.

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']));
// ['-webkit-transition', '-webkit-user-select']
  • 화살표 함수는 함수 자체의 this 바인딩을 갖지 않는다.
  • 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조하는데 이를 lexical this라 한다.
class Person {
  constructor() {
    this.name = 'Lee';
    // 클래스가 생성한 인스턴스(this)의 sayHi 프로퍼티에 화살표 함수를 할당한다.
    // sayHi 프로퍼티는 인스턴스 프로퍼티이다.
    this.sayHi = () => console.log(`Hi ${this.name}`);
  }
}

sayHi 클래스 필드에 할당한 화살표 함수의 상위 클래스는 클래스 외부이다. 하지만 this는 클래스 외부를 참조하지 않고 생성할 인스턴스를 참조한다 따라서 sayHi 클래스 필드에 할당한 화살표 함수 내부에서 참조한 this 는 constructor 내부의 this 바인딩과 같다.

super

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

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

class Derived extends Base {
  // 화살표 함수의 super는 상위 스코프인 constructor의 super를 가리킨다.
  sayHi = () => `${super.sayHi()} how are you doing?`;
}

const derived = new Derived('Lee');
console.log(derived.sayHi()); // Hi! Lee how are you doing?
  • 화살표 함수는 함수 자체의 super 바인딩을 갖지 않는다.
  • 상위 스코프의 super를 참조한다

arguments

(function () {
  // 화살표 함수 foo의 arguments는 상위 스코프인 즉시 실행 함수의 arguments를 가리킨다.
  const foo = () => console.log(arguments); // [Arguments] { '0': 1, '1': 2 }
  foo(3, 4);
}(1, 2));

// 화살표 함수 foo의 arguments는 상위 스코프인 전역의 arguments를 가리킨다.
// 하지만 전역에는 arguments 객체가 존재하지 않는다. arguments 객체는 함수 내부에서만 유효하다.
const foo = () => console.log(arguments);
foo(1, 2); // ReferenceError: arguments is not defined
  • 화살표 함수는 상위 스코프의 arguments를 참조한다.
  • 매개변수를 확정할 수 없는 가변 인자 함수를 구현할 때 유용하다.

REST 파라미터

기본 문법

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

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

function bar(param1, param2, ...rest) {
  console.log(param1); // 1
  console.log(param2); // 2
  console.log(rest);   // [ 3, 4, 5 ]
}

bar(1, 2, 3, 4, 5);
  • Rest 파라미터는 반드시 마지막 파라미터이어야 한다.
function foo(...rest1, ...rest2) { }

foo(1, 2, 3, 4, 5);
// SyntaxError: Rest parameter must be last formal parameter
  • rest 파라미터는 단 하나만 선언할 수 있다.

rest 파라미터와 arguments 객체

function sum(...args) {
  // Rest 파라미터 args에는 배열 [1, 2, 3, 4, 5]가 할당된다.
  return args.reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
  • 화살표 함수는 함수 자체의 argument를 갖지 않음므로 가변인자함수를 구현해야할때는 반드시 rest 파라미터를 사용해야 한다.

매개변수 기본값

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

console.log(sum(1, 2)); // 3
console.log(sum(1));    // 1
  • Rest 파라미터에는 기본값 지정 불가.
  • length 객체와 argument 객체에 아무런 영향을 주지 않는다.

0개의 댓글