화살표 함수

RHUK2·2021년 5월 7일
0

Javascript

목록 보기
35/56

📢 2022/06/10 복습


📚 Reference


javascript.info, https://ko.javascript.info/arrow-functions-basics
javascript.info, https://ko.javascript.info/arrow-functions
PoiemaWeb, https://poiemaweb.com/es6-arrow-function

참고 사이트에 내용을 개인적으로 복습하기 편하도록 재구성한 글입니다.
자세한 설명은 참고 사이트를 살펴보시기 바랍니다.


화살표 함수 기본 문법


ES6에 등장한 화살표 함수(Arrow function)는 function 키워드를 대신하여 함수를 보다 간략하게 표현 가능하고, 기능의 차이가 존재합니다.

// ES5 선언식 함수
function pow(x) { return x * x; };
// ES5 표현식 함수
var pow = function (x) { return x * x; };
// ES6 화살표 함수
const pow = x => x * x;

화살표 함수의 기본 문법은 아래와 같습니다.

// 매개변수 지정 방법
const test = () => { ... }; // 매개변수가 없을 경우
const test = x => { ... }; // 매개변수가 한 개인 경우, 소괄호를 생략할 수 있습니다.
const test = (x, y) => { ... }; // 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없습니다.

// 함수 몸체 지정 방법
const test = x => { return x * x; }; // single line block
// 함수 몸체가 한줄의 구문이라면 중괄호를 생략할 수 있으며
// 암묵적으로 return되고 위 표현과 동일합니다.                       
const test = x => x * x;
const test = () => {
  const x = 10;
  return x * x;
}; // multi line block.

// single line block에서 객체를 반환할 때
const test = () => { return { a: 1 }; }
// 중괄호와 return 생략 시에는 반드시 소괄호가 필요합니다. 위 표현과 동일합니다.
const test = () => ({ a: 1 })

화살표 함수에는 "this"가 없습니다


화살표 함수 본문에서 this에 접근하면, 외부에서 값을 가져옵니다.

이런 특징은 객체의 메서드(showList()) 안에서 동일 객체의 프로퍼티(students)를 대상으로 순회를 하는 데 사용할 수 있습니다.

let group = {
  title: "1모둠",
  students: ["보라", "호진", "지민"],

  showList() {
    this.students.forEach(
      student => alert(this.title + ": " + student)
    );
  }
};

group.showList();

예시의 forEach에서 화살표 함수를 사용했기 때문에 화살표 함수 본문에 있는 this.title은 화살표 함수 바깥에 있는 메서드인 showList가 가리키는 대상과 동일해집니다. 즉 this.titlegroup.title과 같습니다.

위 예시에서 화살표 함수 대신 "일반" 함수를 사용했다면 에러가 발생했을 겁니다.

let group = {
  title: "1모둠",
  students: ["보라", "호진", "지민"],

  showList() {
    this.students.forEach(function(student) {
      // TypeError: Cannot read property "title" of undefined
      alert(this.title + ": " + student)
    });
  }
};

group.showList();

에러는 forEach에 전달되는 함수의 thisundefined 이어서 발생했습니다. alert 함수에서 undefined.title에 접근하려 했기 때문에 얼럿 창엔 에러가 출력됩니다.

그런데 화살표 함수는 this 자체가 없기 때문에 이런 에러가 발생하지 않습니다.


🔥 화살표 함수는 new와 함께 실행할 수 없습니다.

this가 없기 때문에 화살표 함수는 생성자 함수로 사용할 수 없다는 제약이 있습니다. 화살표 함수는 new와 함께 호출할 수 없습니다.


🔥 화살표 함수 vs bind

화살표 함수와 일반 함수를 .bind(this)를 사용해서 호출하는 것 사이에는 미묘한 차이가 있습니다.

.bind(this)는 함수의 "한정된 버전(bound version)"을 만듭니다.
화살표 함수는 어떤 것도 바인딩시키지 않습니다. 화살표 함수엔 단지 this가 없을 뿐입니다. 💥 화살표 함수에서 this를 사용하면 일반 변수 서칭과 마찬가지로 this의 값을 외부 렉시컬 환경에서 찾습니다.


화살표 함수엔 "arguments"가 없습니다


화살표 함수는 일반 함수와는 다르게 모든 인수에 접근할 수 있게 해주는 유사 배열 객체 arguments를 지원하지 않습니다.

이런 특징은 현재 this 값과 arguments 정보를 함께 실어 호출을 포워딩해 주는 데코레이터를 만들 때 유용하게 사용됩니다.

아래 예시에서 데코레이터 defer(f, ms)는 함수를 인자로 받고 이 함수를 래퍼로 감싸 반환하는데, 함수 fms 밀리초 후에 호출됩니다.

function defer(f, ms) {
  return function() {
    setTimeout(() => f.apply(this, arguments), ms)
  };
}

function sayHi(who) {
  alert("안녕, " + who);
}

let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("철수"); // 2초 후 "안녕, 철수"가 출력됩니다.

화살표 함수를 사용하지 않고 동일한 기능을 하는 데코레이터 함수를 만들면 다음과 같습니다.

function defer(f, ms) {
  return function(...args) {
    let ctx = this;
    setTimeout(function() {
      return f.apply(ctx, args);
    }, ms);
  };
}

일반 함수에선 setTimeout에 넘겨주는 콜백 함수에서 사용할 변수 ctxargs를 반드시 만들어줘야 합니다.


this를 포함한 화살표 함수 사용을 피해야 하는 경우


메서드를 정의하는 경우

const person = {
  name: 'Tomas',
  sayHi: () => console.log(`Hi, ${this.name}`)
};

// TypeError: Cannot read property 'name' of undefined
person.sayHi();

화살표 함수는 this가 없기 때문에 외부 실행 컨텍스트의 this를 참조해야 하는데, 위 예시의 경우 전역 실행 컨텍스트를 참조하기 때문에 엄격 모드 기준으로 undefined가 되고 에러가 발생합니다.

프로토타입

const person = {
  name: 'Tomas',
};

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

// TypeError: Cannot read property 'name' of undefined
person.sayHi();

위의 메서드 정의 때와 같은 이유로 에러가 발생합니다.

addEventListener 함수의 콜백 함수

const button = document.getElementById('myButton');

button.addEventListener('click', () => {
  console.log(this === window); // true
  this.innerHTML = 'Clicked button';
});

addEventListener() 함수의 콜백 함수로 화살표 함수를 사용할 경우 thiswindow 객체를 가리키고 엄격 모드에서는 undefined를 가리킵니다.

profile
생각 많이 하지 않기 😎

0개의 댓글