본문 바로가기

푸로그래밍/JS

[JS] 화살표 함수 Arrow Function

반응형

이 함수는 아쉽게도 모든 웹개발자들에게 사랑받는 킹터넷 갓스플로러에서는 사용이 불가하다.

정말정말아쉽다.

 

 

기본문법

일단 기본적으로 일반 함수와의 용법의 차이를 살펴보면 이렇다.

    	function testFunc(arg = 'aaaa'){
        	console.log(arg);
        }
        
        let testFunc = function(arg = 'aaaa'){
        	console.log(arg);
        }
        
        let testFunc = (arg = 'aaaa') => {
        	console.log(arg);
        }
    

이렇게 텍스트로 살펴만 보면 형식의 차이일뿐 별다른 차이는 보이지 않는다.

이런식으로 기존 함수형태와 같이 기본값을 정해 줄 수도 있다.

물론 전개식도 사용이 가능하다.

 

 

    	let testFunc = arg => console.log(arg);
    

이렇게 인수가 하나일때는 매개변수 괄호를 생략할 수 있다.

인수가 두개 이상일때는 상략할 수 없다.

 

 

    	let testAdd = (x, y) => x + y;
    

함수의 내용이 한줄일때는 중괄호를 생략하고 위와같이 작성할 수 있다.

위와같이 중괄호를 생략하고 작성할 경우 그 한줄이 return값이 된다.

따라서 위의함수를 실행하면

이렇게 된다.

 

 

 

ArrowFunction에서의 Scope

lexical this, dynamic this 같은건 여기서는 설명하지 않는다. 필자가 처음 공부할때 몰랐던 부분, 이해가 힘들었던 부분을 기준으로 쓴다.

위에서는 일반함수와 화살표함수의 문법적 차이만을 살펴보았다. 하지만 진짜 중요한 부분은 scope이다.

    	let someElement = document.querySelector('someSelector');
        someElement.addEventListener('click', function(){
        	console.log(this, someElement);
        });
    

일반적인 addEventListener 함수를 예로 들어보자.

클릭후 callBack부분에 저런식으로 코드를 짰을때 일반적으로 this는 click된 주체인 someElement가 된다.

someElement.click(); 은 클릭하는 부분을 가시적으로 나타낼 수 없기에 의도적으로 클릭 이벤트를 일으킨 것이다.

 

 

이것은 jQuery의 on으로 event를 binding했을때도 같은 결과가 나타난다. 물론 일반객체와 jquery객체는 다르지만 궁극적으로, 화살표함수가 아닌 일반함수를 사용했을때에는 this와 someElement변수가 같은 element를 가리키고 있다.

 

 

반면에 화살표함수를 사용했을때의 결과값을 보자.

    	let someElement = document.querySelector('someSelector');
        someElement.addEventListener('click', () => {
        	console.log(this, someElement);
        });
    

결과는 아래와 같다.

 

 

 

사실 javascript에서 함수는 함수이면서 클래스라고도 할 수 있다.

이게 뭔 개소리냐 하면

    	// 예제 a-1
        function a(){
        	console.log(this);
        }
        let res = a();
    

이렇게 하면 일단 특별한건 없고 그냥 함수이다.

생성자를 통해서 만들어진 객체도 아니기 때문에 저 함수의 상위 스코프가 없다고 놓고, 저렇게 실행을 시켜보면 javascript 최상위 Scope인 window객체가 튀어나올 것이다.

 

님들이 자주 쓰는 document.querySelector함수는 document객체의 querySelector함수 라는 뜻이고

그 document가 선언되어있는 부분이 바로 window이다.

그래서 풀네임을 적어보면 window.document.querySelector이다.

window Scope에 선언되어있는 필드들은 그냥 바로 사용할 수 있다.

 

아무튼 a라는 함수를 위의 예제 a-1 처럼 그저 실행을 시키면 하나의 함수로써 console.log를 수행한다.

함수로써의 a는 return이 없으므로 아무것도 반환하지 않는다.

따라서 res를 console.log로 찍어보면 undefined가 나올것이다.

 

 

그러나 아래의 예를 보자

    	// 예제 a-2
        function a(){
        	console.log(this);
        }
        let res = new a();
    

위에서 함수는 함수이면서 클래스라고 했다. 객체지향 프로그래밍에서 클래스는 객체의 설계도를 나타낸다.

 

예제 a-2 와 같이 new를 통해서 객체를 만드는 순간 하나의 생성자로써 작동을 하게 된다.

따라서 타 객체지향 언어에서 new를 통해서 객체를 생성한 것과 같이, res에는 함수a를 클래스로써 기반으로 만들어진 하나의 객체가 들어오게 된다.

 

함수 a가 생성자로써 작동하게 되면서 만약 함수 a안에 변수가 있으면 선언이 되고(맴버필드),

함수를 선언하면 함수가 선언이 되어 맴버메소드가 생길것이며,

위의 console.log(this)와 같이 함수를 호출하면 호출이 될것이다,

 

실제로 예제 a-2처럼 new a();를 하면 console.log(this);가 실행이 되는데, 예제 a-1의 결과와는 다를것이다.

함수a를 클래스로써 만들어진 객체의 구조가 콘솔에 찍히게 된다.

왜냐하면 new 를 하는순간 새로운 객체가 생성 되어 그 객체만의 새로운 scope가 생겼기 때문이다.

 

 

 

Javascript에서의 화살표함수가 아닌 일반함수는 모두 자기만의 this를 가진다. 

생성자인 경우에는 자신의 객체,

객체의 메소드로써 사용된 경우에는 문맥객체를 this로 가진다.

 

실제로 new a();할때 console에 출력된 것은 새로운 a객체이다.

객체를 만들고 (testFunc, testfuncArrow) 맴버 메소드(객체의 메소드)를 호출했다. 그리고 res자체를 콘솔에 찍었다.

동일한 a객체가 나온다.

 

testFunc는 기본함수인데 객체의 메소드로써 자신의 문맥객체(a)를 this로 가졌다.

 

testfuncArrow는 화살표함수이기에 자신의 this를 가지지 않는다.

따라서 화살표함수 내에서 this를 사용하면 이는 객체 a의 this가 된다.

a객체의 this는 a객체 그 자체를 나타낸다.

여기까지는 Scope에 따른 this의 차이가 잘 나타나지 않는다. 모두 같은 값을 가지고 있기 때문이다.

 

 

 

그럼 이제 차이를 보자.

setTimeout의 callback으로 화살표함수가 아닌 일반함수를 사용했을 때는 setTimeout이 속해있는 Window객체가 뜬다.

반면에 callback으로 화살표함수를 사용했을 때는 자신만의 this를 따로 갖지 않으므로 자신의 상위 Scope의 this인 a객체가 뜬다.

 

그래서 자신의 상위 객체에 어던부분을 손대고 싶을때 일반함수를 이용한 setTimeout에서는 this키워드를 사용하면 안되고, 객체(상위 scope)에 let _this = this;와같이 변수로 빼놓고 사용하여야 한다.

반면에 화살표함수를 사용했을 경우에는 자신만의 this를 가지지 않기 때문에 this사용시 바로 상위 scope를 가져올 것이고, 위의 코드에서는 바로 a객체를 가져올 수 있다.

 

 

더 짧고 간단하다는 이유로 남발해서는 안된다. 자신에게 필요한 상황에 맞게 선택해야 한다.

화살표 함수를 적용하면 좋은 경우에대해서 나중에 간략하게 글을 작성할 것이다.

그럼 ㅅㄱ

 

반응형