JavaScript ES6+ (6) Arrow function

염겨레·2020년 11월 30일
0

javascript-ES6-basic

목록 보기
6/8

이 글은 정재남 개발자님의 인프런 강의인 JavaScript ES6+ 제대로 알아보기 초급편을 정리한 내용입니다.

1. Arrow function

(1) 기본 사용 예제

Arrow function을 사용하면 => 표기를 사용해 함수를 축약할 수 있습니다.

let a = function() {
  return new Date();
};

let b = function(num) {
  return num * num;
};

let c = function(num1, num2) {
  console.log(num1, num2);
};

let d = function(x) {
  return {
    x: x
  };
};

let e = function(a) {
  return function(b) {
    return a + b;
  };
};

위의 함수들을 Arrow function을 사용하면 아래와 같이 축약할 수 있습니다.

let a = () => new Date();

let b = num => num * num;

let c = (num1, num2) => {
  console.log(num1, num2);
};

let d = x => ({x});

let e = a => b => a + b;
// 사용: const num = e(1)(2);

내용을 정리하면 아래와 같습니다.

  • (매개변수) => {본문}와 같은 형식으로 작성한다.
  • 매개변수가 하나인 경우() 괄호를 생략 가능하다.
  • 매개변수가 없을 경우에는 () 괄호가 필수이다. _$를 사용해 매개변수를 사용하지 않을 것임을 명시적으로 보여줄 수 있지만, 되도록 ()를 사용하는 것이 좋다.
  • 본문이 return만 할 경우 {} 괄호와 return 문이 생략 가능하다.
  • return 하는 것이 객체{}일 경우에는 괄호를 사용해야 한다.

(2) 실행 컨텍스트 생성시의 this 바인딩을 하지 않는 arrow functin

예제를 먼저 보겠습니다.

const obj = {
  a() {
    console.log(this);		// {a: f}
    
    const b = function() {	
      console.log(this);	// window
    };
    
    b();
  }
};
obj.a();

obja 메소드 내부의 b 함수this를 바인딩해서 전역객체인 window를 할당하였습니다. 그렇다면 b 함수를 arrow function으로 선언하면 어떻게 될까요?
그 경우에는 아래와 같이 this를 바인딩 하지 않고 외부 스코프에서 this를 찾아 a 메소드 내부의 첫 번째 줄의 this와 같은 결과를 도출하게 됩니다(블록 스코프에서 처럼). 이 경우처럼 arrow function을 사용하게 되면 함수 내부에서 this를 사용하기 위해 this를 인자로 넘겨주거나 명시적으로 call 메소드를 사용하지 않아도 됩니다.

const obj = {
  a() {
    console.log(this);		// {a: f}
    
    const b = () => {	
      console.log(this);	// {a: f}
    };
    
    b();
  }
};
obj.a();

arrow function은 함수 스코프인지 블록 스코프인지 확인하기 위해서 arrow function 내부에서 var 변수를 선언하고 외부에서 접근해 볼 수 있습니다. 함수 스코프라면 console.log로 출력했을 때 에러가 날 것이고, 블록 스코프일 경우 var는 외부에서 선언한 것처럼 작동하기 때문에 정상적으로 출력이 될 것입니다.

const a = () => {
  var b = 100;
};
console.log(b);		// reference error

하지만 console.log로 출력했을 때 reference error가 발생하게 되고, 위의 사례들을 종합했을 때 arrow function은 함수 스코프를 생성하지만 실행 컨텍스트시 this를 바인딩하지 않음을 알 수 있습니다.

(3) 활용 예제

var total = 0;
const obj = {
  nums: [70, 80, 90, 100],
  getNums: function() {
    this.total = 0;	// this: obj
    this.nums.forEach(function(v) {	// => arrow function으로
      this.total += v;	// this: window
    });
  }
};
obj.getNums();
console.log(total);	// 340
console.log(obj.total);	// 0

위 예제에서는 forEach 내부에서 사용한 this가 obj일 것이라고 예상했지만 그렇게 하기 위해서는 this 인자를 따로 넘겨주어야 한다. 하지만 이를 쉽게 해결하는 방법은 forEach 내부 함수를 arrow function으로 활용하면 this를 바인딩하지 않아 내부 this를 외부스코프에서 찾아 obj로 인식하게 된다.

(4) 명시적으로 this를 바인딩할 수 없음.

this를 바인딩하는 call과 같은 메소드로 this를 바꿀 수 없지만, 메소드 자체를 사용할 수 없는 것은 아니다. 아래 예제와 같다.

const sum = (...arg) => {
  console.log(this);	// window
  return arg.reduce((p, c) => p + c);
}

sum.call({}, 1, 2, 3, 4, 5);	// 15

위에서 this{}로 바인딩하고자 했지만 출력한 thiswindow가 도출되었다. 하지만 인자로 준 1, 2, 3, 4, 5는 정상적으로 넘어가 작동하였다.

(5) 생성자 함수로 사용할 수 없음.

function a() {		// 기존 함수 선언
	console.log(this);
}

const b = () => {	// arrow function
  console.log(this);
}

console.dir(a);
console.dir(b);

위 예제를 수행했을 때 console.dir를 출력했을 때 나타나는 두 함수의 차이점은 arrow function은 prototype이 없다는 점이다. 이로 알 수 있는 점은 arrow function은 const c = new b();와 같이 생성자 함수로 사용할 수 없다는 것이다. 쉽게 말하면 메소드는 메소드로만 작동하고, arrow function은 함수로서만 작동하는 것이다. 마지막 예제를 보고 마치도록 하겠다.

const obj = {
  name: 'Son',
  a() {
    return this.name;
  },
  b: () => {
    return this.name;
  }
};

console.log(obj.a());	// "Son"
console.log(obj.b());	// ""

둘 다 메소드 형식으로 호출하기는 했지만, arrow function으로 선언한 b 함수의 경우에는 thisobj가 바인딩되지 않고 windowname을 출력하였다. b 함수는 함수로서 작동한 것이다.

강의를 보고 정리하기는 하였지만, 정리하면서도 이해가 되지 않는 부분들이 아직 많은 것 같다. 정리한 부분에 잘못 이해한 것이 있기도 한 것 같다. 다시 정리해봐야겠다. 끝😭

profile
차근차근 나아가는 시나브로 개발자

0개의 댓글