ECMAScript2015(ES6) 기초 문법
ECMAScript 2015에는 많은 기능들이 추가 되었는데 그 중에 몇가지 기본적인 문법들을 정리해 본다.
- let/const에 의한 블록 스코프
- Map/Set/WeakMap/WeakSet에 의한 컬렉션
- 형을 정의하는 클래스
- 제너레이터/for..of
- Promises
- Template String Literals
- 화살표 함수
- 모듈
let 키워드
가장 먼저 변수 선언에 대하여 알아보자. 기존 Javascript 에서는 var 로 거의 통일되다 시피 변수를 선언하였다.
다만 var 의 문제점은 scope 에 있다.
var 의 scope 는 function 안에서 모두 접근 하게 되는데, 이는 타 언어 출신의 개발자를 헷갈리게 만들고 자칫 잘못하면 엄청난 버그를 만들어내는 방식이다.
1 | var a = 1; // global variable |
위와 같이 Test1() 함수에서 전역변수인 a를 호출하고 변수 b를 지정하였다.
if 문안에서 변수 c를 지정하고 지역변수인 b를 호출하였다.
그리고 if문 밖에서 변수 c를 호출하였다.
이는 에러를 야기 시키지 않는가? 타 언어에서는 c가 if문 안에 있으니 undefined 라고 나올 수 있을꺼다 라고 하지만 자바스크립트에서는 그렇지 않다.
자바스크립트에서 변수의 범위는 function 즉 , 최초의 부모함수 (여기서는 Test1 함수) 가 되기 때문에 해당 코드의 실행 결과로 1 , 2 ,3 이 나타난다.
ES6 에서는
이를 보완하기 위해 let 이라는 block scope 의 변수를 선언하는 형식을 만들었다.
1 | let a = 1; |
var 를 let 으로 변경하였다. a 는 여전히 전역변수가 되어있고 b 는 Test1 함수내에 어디서든 호출이 가능하며,
문제는 c 이다. 해당 함수를 실행하면 c는 나타나지 않는다.
let 으로 변경한 지금 c 변수는 if 문 안에서만 통용되도록 변경되었다. 타 언어의 변수 scope 와 같아진것 이다.
여기서 또 한가지 같은 범위 안이라면 var 는 이미 선언한 변수를 같은 이름으로 덮어 씌우는게 가능하다.
하지만 let 은 그렇지 않다.
1 | var a = 1; |
위 코드 처럼 let 은 같은 범위내에서 같은 이름으로 덮어 씌우려 할 경우 Type Error 를 발생시킨다.
Const 키워드
Const 키워드는 let 과 같이 block scope 를 가지며, let 과 다른점은 상수로 선언된다는 점이다.
기존의 var 로 선언했을 시에는 프로그램 어디서나 해당 변수에 접근하여 값을 고칠 수 있다.
하지만 const 로 선언한다면 상수로 선언되기에 값을 변경시에는 에러가 발생하게 된다.
1 | var r = 4; |
위 코드를 보면 var 로 선언한 pi 변수는 얼마든지 변경 할 수 있기에 단지 상수라고 생각하고 적어놨을 뿐 전혀 상수의 기능을 못 하고 있다.
하지만 const 로 선언한 변수는 값의 변경을 시도 했을 때 읽기 전용 예외 가 발생하며 변경이 되지 않는다.
1 | var a = { |
const 범위는 let 과 같으며 만약 객체를 const 로 선언했을 경우 객체안의 내용은 변경이 가능하지만 객체 자체를 재정의 하는 것은 불가능하다.
…배열 연산자(Spread Operator)
기존 자바스크립트에서 배열 값을 인자로 넘길때는 apply 메소드를 사용하여 넘겼다.
하지만 … 연산자를 사용하여 더욱 간단하게 인자값을 넘길 수 있다.
1 | function Test1(a,b) { |
… 연산자는 배열에 있는 값을 하나하나 꺼내서 개별적인 함수 인자로 만들어서 호출 한다.
… 연산자를 응용하면 다음과 같이도 사용할 수 있다.
1 | let data1 = [1, 2, 3]; |
첫번째로 data3 배열은 data1 과 data2 의 배열을 포함시키는데 여기서 … 연산자를 사용하였다.
두번째로 배열에 배열을 push 할때 기존의 Array.prototype.push.apply(arr1,arr2) 가 아닌 좀 더 깔끔하고 간결하게 push 사용이 가능하다.
마지막으로 함수의 인자로 값을 넘길때 여러개의 배열을 … 연산자를 사용하여 넘길 수 있다.
배열
ES6 에서 간편해진 배열관련 문법들을 살펴보자.
위 … 연산자를 활용하는 방법과 그 외 기존에 쓰던 방법을 더욱 간단하게 표현할 수 있도록 ES6는 많은 변화가 있다.
먼저 배열에 값을 할당 할 때의 예제를 살펴보자.
1 | // ES5 |
배열 값을 할당하는 방법이 아주아주 간단해 진 걸 볼 수 있을 것이다.
여기서 배열 값의 건너뜀 과 응용하여 위에서 배운 … 연산자를 사용해보자.
1 | let array = [1,2,3]; |
위 코드를 보면 배열에 값을 지정할 때 중간값을 건너뛰는 것이 가능하다.
그리고 … 연산자를 이용하여 배열의 남은 값들을 다 포함시킬 수도 있고 , 역시 값을 건너뛰면서도 … 연산자가 사용가능 한 것을 볼 수 있다.
1 | let array = [1,2]; |
첫번째 배열에서는 c에 기본값을 주고 출력하는 것을 볼 수 있다.
그리고 함수의 인자값에도 기본값을 주고 출력이 가능한 것을 확인 할 수 있다.
객체
1 | //ES5 |
ES6 에서는 객체 값을 변수에 할당할 때 변수를 객체 값의 이름과 같이 만들어서 할당하는 방법이 있다.
그리고 마지막 부분은 변수의 이름을 객체 값과 같은 것이 아닌 다른 이름을 쓰고자 할때의 예제이다.
Arrow function
ES6 부터 Arrow function 이 추가 되었다.
(파라미터)=> {함수 본체};
1 | //ES5 |
코드를 보면 알 수 있듯이 함수를 간결하게 표현할 수 있도록 바뀌었다.
함수의 return 문이 하나인 경우에 3번째 예제처럼 한줄로 만들 수도 있다.
Arrow function 의 가장 중요한 특징은 this 값의 scope 변경이다. 예제를 살펴보자.
1 | var a = 1; |
위 코드는 es5 에서 this 의 scope 를 나타낸다. es5 에서는 this 의 scope 가 기본적으로 전역객체 (브라우저라면 window)
를 가르키고 있으며 함수를 만들어도 this 값은 여전히 window 객체를 가리키고 있다.
하지만 object 를 만들게 되면 this 는 자신을 호출한 object 를 가리키게 되며 object1 의 test 를 보면 알 수 있다.
이런 부분은 callback 함수를 만들 었을 때 문제가 생긴다.
test 의 내부 함수를 보면 해당 함수의 this 는 object1 을 가리키지 않고 여전히 window 객체를 가리키고 있다.
왜 그런고 하니 내부함수는 객체의 멤버 메서드가 아닌 단지 호출된 함수 일 뿐이다.
그럼 function 이라는 놈을 가지고 있는 부모 객체는 누구인가? 바로 전지전능한 window 객체가 된다.
그렇기 때문에 내부 함수에서는 this 가 global 객체 를 가리키게 된다.
이를 해결하기 위해 object1 의 test2 함수처럼 함수 선언시에 this 를 임의의 변수에 넣어서 쓰는 방법을 사용한다.
( 보통 that 또는 self , _this 등의 이름을 쓴다. ) 그리고 내부 함수에서는 이를 호출하여 사용하게 되는데 , arrow function 에서는 이런 부분이 해결된다.
위 코드의 object1 을 arrow function 을 이용하여 만들어 보자.
1 | let a = 1; |
코드의 결과를 보면 내부 함수의 this 가 가리키는 곳이 window 가 아닌 object1 으로 바뀌었다.
이는 이전의 this 범위와 다르게 자신을 둘러싸는 문맥의 this 값을 가진다.
참고로 Arrow function 은 new 연산자를 사용할 수 없다.
객체 리터럴
ES6 에서 객체 리터럴로 프로퍼티를 생성하는 새로운 구문이 있다.
1 | let first = 'one'; |
2진수 , 8진수 표현 방식
ES6 에서의 2진수와 8진수 표현 방식을 보자. 예전에는 자바스크립트 만으로는 2진수를 나타낼 방법은 없었다.
하지만 ES6 에서는 숫자앞에 0b 를 붙이면 자바스크립트 엔진이 2진수로 처리하게 된다.
더불어 8진수를 표현할 때 숫자 앞에 0을 붙여서 표기를 하였다. 하지만 이는 초심자에게 헷갈릴 수 있다고 판단, 0 이 아닌 0o 를 붙이는 것 으로 변경되었다.
1 | //ES6 2진수 표현 |