화살표 함수

화살표 함수의 선언

// 매개변수 지정 방법  
()  =>  {  ...  }  // 매개변수가 없을 경우  
x  =>  {  ...  }  // 매개변수가 한 개인 경우, 소괄호를 생략할 수 있다.  
(x,  y)  =>  {  ...  }  // 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없다.  
// 함수 몸체 지정 방법  
x  =>  {  return  x  *  x  }  // single line block
x  =>  x  *  x  // 함수 몸체가 한줄의 구문이라면 중괄호를 생략할 수 있으며 암묵적으로 return된다. 위 표현과 동일하다.  
()  =>  {  return  {  a:  1  };  }  
()  =>  ({  a:  1  })  // 위 표현과 동일하다. 객체 반환시 소괄호를 사용한다.  
()  =>  {  // multi line block.  
	const  x  =  10;  
	return  x  *  x;  
};

화살표 함수의 호출

화살표 함수는 익명 함수로만 사용할 수 있다. 따라서 화살표 함수를 호출하기 위해서는 함수 표현식을 사용한다.

// ES5  
var  pow  =  function  (x)  {  return  x  *  x;  };  
console.log(pow(10));  // 100
// ES6  
const  pow  =  x  =>  x  *  x;  
console.log(pow(10));  // 100

콜백 함수로 사용할 수 있다. 이 경우 일반적인 함수 표현식보다 표현이 간결하다.

// ES5  
var  arr  =  [1,  2,  3];  
var  pow  =  arr.map(function  (x)  {  // x는 요소값  
	return  x  *  x;  
});  
console.log(pow);  // [ 1, 4, 9 ]
// ES6  
const  arr  =  [1,  2,  3];  
const  pow  =  arr.map(x  =>  x  *  x);  console.log(pow);  // [ 1, 4, 9 ]

this

function 키워드로 생성한 일반 함수와 화살표 함수의 가장 큰 차이점은 this이다.

1. 일반 함수의 this - 콜백함수 내부의 this는 전역객체 window를 가리킨다.
2. 화살표 함수의 this - 화살표 함수는 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정된다. 동적으로 결정되는 일반 함수와는 달리 **화살표 함수의 this 언제나 상위 스코프의 this를 가리킨다.** 이를 **Lexical this**라 한다.
function  Prefixer(prefix)  {  
	this.prefix  =  prefix;  
}  
Prefixer.prototype.prefixArray  =  function  (arr)  {  
// this는 상위 스코프인 prefixArray 메소드 내의 this를 가리킨다.  
	return  arr.map(x  =>  `${this.prefix}  ${x}`);  
};  
const  pre  =  new  Prefixer('Hi');  
console.log(pre.prefixArray(['Lee',  'Kim']));

화살표 함수는 call, applay, bind 메소드를 사용하여 this를 변경할 수 없다.

window.x  =  1;  
const  normal  =  function  ()  {  return  this.x;  };  
const  arrow  =  ()  =>  this.x;  
console.log(normal.call({  x:  10  }));  // 10  
console.log(arrow.call({  x:  10  }));  // 1

화살표 함수를 사용해서는 안되는 경우

  1. 메소드

    // Bad  
    const  person  =  {  
    	name:  'Lee',  
    	sayHi:  ()  =>  console.log(`Hi ${this.name}`)  
    };  
    person.sayHi();  // Hi undefined
    // Good  
    const  person  =  {  
    	name:  'Lee',  
    	sayHi()  {  // === sayHi: function() {  
    		console.log(`Hi ${this.name}`);  
    	}  
    };  
    person.sayHi();  // Hi Lee
    

    메소드로 정의한 화살표 함수 내부의 this는 메소드를 소유한 객체, 즉 메소드를 호출한 객체를 가리키지 않고 상위 컨택스트인 전역 객체 window를 가리킨다. 따라서 화살표 함수로 메소드를 정의하는 것은 바람직하지 않다.

  2. prototype

    // Bad  
    const  person  =  {  
    	name:  'Lee',  
    };  
    Object.prototype.sayHi  =  ()  =>  console.log(`Hi ${this.name}`);  
    person.sayHi();  // Hi undefined
    // Good  
    const  person  =  {  
    	name:  'Lee',  
    };  
    Object.prototype.sayHi  =  function()  {  
    	console.log(`Hi ${this.name}`);  
    };  
    person.sayHi();  // Hi Lee
    
  3. 생성자 함수 화살표 함수는 생성자 함수로 사용할 수 없다. 생성자 함수는 prototype 프로퍼티를 가지며 prototype 프로퍼티가 가리키는 프로토타입 객체의 constructor를 사용한다. 하지만 화살표 함수는 prototype 프로퍼티를 가지고 있지 않다.

    const  Foo  =  ()  =>  {};  
    // 화살표 함수는 prototype 프로퍼티가 없다  
    console.log(Foo.hasOwnProperty('prototype'));  // false  
    const  foo  =  new  Foo();  // TypeError: Foo is not a constructor
    
  4. addEventListener 함수의 콜백 함수 addEventListener 함수의 콜백 함수를 화살표 함수로 정의하면 this가 상위 컨택스트인 전역 객체 window를 가리킨다.

    // Bad  
    var  button  =  document.getElementById('myButton');  
    button.addEventListener('click',  ()  =>  { 
    	console.log(this  ===  window);  // => true  
    	this.innerHTML  =  'Clicked button';  
    });
    // Good  
    var  button  =  document.getElementById('myButton');  
    button.addEventListener('click',  function()  {  
    	console.log(this  ===  button);  // => true  
    	this.innerHTML  =  'Clicked button';  
    });