안녕 ES6. (1/4) 변수와 화살표 함수, 파라미터.

let과 const

let은 많은 부분에서 var를 대채할 것으로 기대된다. let은 var와 달리 변수의 스코프를 블록 또는 표현식 단위로 제한한다. 자바스크립트의 변수범위와 호이스팅에서 설명했던것과 완전 반대로 작동한다.

잘못된 예제. (블럭-수준 범위로 오해할 경우)

1
2
3
4
5
6
7
8
var name = "Richard";
// 아래의 if문은 name변수에 대한 지역-범위를 생성하지 않습니다.
if (name) {
name = "Jack";
console.log(name); // Jack : 전역 변수
}
// name은 여전히 전역변수이며 if문에서 변경되었습니다.
console.log(name); // Jack

ES5에서 변수의 범위를 이렇게 설명했었다. var로 선언된 변수는 함수내에서 전역범위를 가지므로 위와 같이 작동한다. 하지만, if문내의 name을 let으로 선언할 경우는 바깥의 name과 내부의 name은 다른 스코프를 가지게 된다.

1
2
3
4
5
6
7
8
var name = "Richard";
if (name) {
let name = "Jack"; // name은 if문의 지역범위를 가진다.
console.log(name); // Jack : 지역 변수
}
// name은 if문에서 변경되지 않았다.
console.log(name); // Richard

만일, 다음과 같이 let의 위치가 바뀌면 어떻게 될까?

1
2
3
4
5
6
7
8
let name = "Richard";
if (name) {
name = "Jack"; // name은 함수의 지역범위를 가진다.
console.log(name); // Jack : 전역 변수
}
// name은 if문에서 변경되었다.
console.log(name); // Jack

이 경우에 let은 var와 동일하게 사용된다. name이 블록 스코프를 가지기 위해서는 if문 내에서 선언되어야 한다.

const는 상수처럼 작동(Immutable)한다. 가급적, 상수 선언은 대문자로 쓰도록 하는게 좋겠다. 또한, 함수선언과 같은 경우에 var보다 const를 사용하는 편이 낫다. 즉, let과 const를 적절히 쓰면 메모리도 아끼고, 디버깅도 좀 더 수월해진다.

앞길이 구만리인데 고작 let, const 로 한페이지를 채워버렸다. 하지만, 사소한것도 확실히 알고 넘어가야 한다. 버그는 늘 사소한데서 생겨나고 그런게 찾기는 드럽게 힘들기 마련이다.(T.T)

화살표 함수와 this

ES5에서 가장 헷갈리는것이 바로 this의 범위이다. 클로저가 생성한 컨텍스트로 인해 this가 this가 아닌 상황이 발생하여 “that = this, self = this”와 같은 패턴을 사용해야만 했다.

Arrow vs. Prototype

1
2
3
4
var self = this
$('.btn').click(function(event){
self.sendData()
})

또는 “.bind(this)”를 사용해 this를 현재 컨텍스트와 수동으로 바인딩하기도 했었다.

1
2
3
$('.btn').click(function(event){
this.sendData()
}.bind(this))

화살표 함수를 사용하면 이러한 번거로움을 해소할 수 있다.

1
2
3
$('.btn').click((event) =>{
this.sendData()
})

화살표 함수는 함수 표현식을 간략하게 표기하도록도 해주지만 this의 범위를 함수를 감싸는 코드와 동일하게 유지해줌으로써 기존의 클로저로 인한 번거로움을 많이 해소해 준다.

파라미터

ES5에서 arguments를 대신해 “…”식을 지원한다.

1
2
3
4
5
6
const myFunc = (...params) => {
console.log(params.length + ' argument(s)');
};
// execute it
myFunc(1,2,3);
// 3 arguments;

params는 자바스크립트에 내장된 arguments와 같다. 즉, 기존 코드라면 “params.length”는 “arguments.length”와 동일하다. 나은점은, “arguments”가 아닌 “params”와 같이 이름을 붙일수 있다는것과 믹스인형태로 사용할 수 있다는 점이다.

1
2
3
4
5
6
const drink = function(requiredParam , ...maybe) {
//
}
drink('coffee');
drink('coffee' , 'sugar');
drink('coffee' , 'sugar' , 'milk');

또한, 원하는 파라미터에 기본값을 줄 수도 있다.

1
2
3
4
5
6
7
const drink = (typeOfDrink = 'coffee' , ...maybe) => {
// ...
};
const eat = (food , todo='wash hand' ) => {
};

위외 같은 코드를 ES5에서는 통상 아래와 같은 패턴으로 코딩을 하게된다.

1
2
3
4
5
6
var drink = function(typeOfDrink) {
typeOfDrink = typeOfDrink || 'coffee';
if (arguments.length > 2) {
// ... loop whatever
}
};

and

꼭 필요하다 싶은것들만 묶어서 한편으로 간단하게 쓰려고 했는데 주절주절 쓰다보니 길어졌다. 아직 클래스도 남았고, 제너레이터, Map/Set, 디스터럭처링등 다룰게 많아서 또 시리즈로 가야겠다. See ya!