JavaScript

[DeepDive] - 26장(ES6 함수의 추가기능) 필요 내용 정리

메서드

  • ES6 사양에서의 메서드는, 메서드 축약 표현으로 정의된 함수만을 의미한다.
  • ES6 사양에서 정의한 메서드는 인스턴스를 생성할 수 없는 non-constructor이다. 따라서 생성자 함수로서 호출할 수 없다. 추가로 ES6의 메서드는 인스턴스가 없기 때문에 prototype 프로퍼티 및 프로토타입이 없다.
const obj = {
  x:1,
  // foo는 메서드
  foo(){
    return this.x
  }
  ,
  // bar는 메서드가 아닌, 일반함수    
  bar: function(){
    return this.x;
  }
}

obj.foo() // 1
obj.bar() // 1

new obj.foo() // TypeError: obj.foo is not a constructor

new obj.bar() // bar { __proto__: { constructor: ƒ bar() } }

 

화살표 함수

  • 화살표 함수는 인스턴스를 생성할 수 없으므로 (non-constructor) 메서드와 마찬가지로 prototype 프로퍼티 및 프로토타입이 없다.
  • 중복된 매개 변수를 불허한다.

화살표 함수에서의 this

  • 화살표 함수의 this는, 일반 함수의 this와 다르게 동작한다. 이는 "콜백 함수 내부의 this 문제이다. 즉, 콜백 함수 내부의 this가 외부 함수의 this와 다르기 때문에 이를 해결하고자 의도적으로 설계되었다.
class Prefixer {
  constructor(prefix){
    this.prefix = prefix;
  }

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

const prefixer = new Prefixer("-webkit-");
console.log(prefixer.add(["transition","user-select"])) // TypeError: Cannot read properties of undefined (reading 'prefix')
  • 위와 같이, TypeError: Cannot read properties of undefined (reading 'prefix') 에러가 발생하는 이유는 다음과 같다.
    • map에 콜백으로 전달되는 함수는 일반함수로서 호출
    • 클래스 내부에는, 암묵적으로 strict mode 적용
    • strict mode에서 일반 함수로서 호출된 모든 함수 내부의 this는 전역 객체가 아닌 undefined 바인딩
  • 위의 this문제를 해결하기 위해 아래와 같은 1~3 방법도 있지만, ES6 이후로는 화살표 함수를 활용하여 해결할 수 있다.

  // 해결 방법1: that 활용
  add(arr) {
    const that = this;
    return arr.map(function(item){
      return that.prefix + item;
    })
  }

  // 해결 방법2: map 2번째 인자 this 전달
  add(arr) {
    return arr.map(function(item){
      return this.prefix + item;
    },this)
  }

  // 해결 방법3: bind 활용
    add(arr) {
    return arr.map(function(item){
      return this.prefix + item;
    }).bind(this)
  }

    // 해결 방법4: 화살표 함수 사용 
    add(arr) {
    return arr.map((item) => {
      return this.prefix + item;
    })
  }
  • 화살표 함수는 함수 자체의 this 바인딩 값을 갖고 있지 않으며 상위 스코프의 this를 참조하게 되는데, 이를 lexical this라고 한다.

 

Rest 파라미터

Rest 파라미터란?

  • 함수에 전달된 인수들의 목록을 배열로 전달받는 문법이다.
  • 일반 매개변수와 Rest 파라미터의 혼용이 가능하며, 이름 그대로 먼저 선언된 매개변수에 할당된 인수를 제외한 나머지 인수들로 구성된 배열이 할당되므로 전달되는 인자들의 마지막에 위치해야 한다.
  • Rest 파라미터는 단 하나만 선언할 수 있다.
function foo(param,...rest) {
  return {
    param, rest
  }
}

foo(1,2,3,4,5) // { param: 1, rest: [ 2, 3, 4, 5 ] }

function foo(...rest,param) {
  return {
    param, rest
  }
}

foo(1,2,3,4,5) // SyntaxError: Rest element must be last element. 

Rest 파라미터와 arguments 객체

  • arguments 객체는, 함수 호출시 인수들의 정보를 담고 있는 순회 가능한 유사 배열 객체이다.
  • 함수 내에서 지역 변수처럼 사용이 가능하다.
  • arguments 객체는 배열이 아닌 유사배열 객체이므로 배열 메서드를 사용하려면 배열로 변환해야하는 번거로움이 있었지만, ES6 이후 Rest 파라미터를 사용하면서 이와 같은 번거로움을 피할 수 있었다.
  • 화살표 함수의 경우, arguments 객체를 갖기 않기 때문에 화살표 함수를 사용할때는 Rest 파라미터를 사용해야 한다.
function foo() {
  console.log(arguments)
};

function bar() {
  const resultArray = Array.prototype.slice.call(arguments)
  console.log(resultArray)
};

const wrongArrow = (...rest) => {
  // ReferenceError: arguments is not defined
  console.log(arguments)

}

const correctArrow = (...rest) => {
console.log(rest)  
}

foo(1,2,3) // { '0': 1,'1': 2,'2': 3,length: 3, callee: ƒ foo(),__proto__: {...}}

bar(1,2,3) // [ 1, 2, 3 ]

wrongArrow(1,2,3) // ReferenceError: arguments is not defined

correctArrow(1,2,3) // [ 1, 2, 3 ]