전통적으로 자바스크립트는 함수스코프와 전역스코프만을 지원하여 변수의 생명주기 및 접근을 제어해왔다. 하지만 ES6 에서부터는 블록스코프도 지원하게 되었다. 이를 가능하게 해주는것이 let 과 const 이다. 아래의 코드는 블록 스코프를 따르는 여타 언어에서는 에러를 발생시켰을 것이다. 하지만 함수스코프와 전역스코프를 따르는 자바스크립트에서는 문제없이 작동된다. 그러나 이는 많은 에러와 버그의 원인이였으며 , let과 const 가 도입된 이유이다.
if(false){
var x = 'hello'
}
console.log(x) ; //undefined
이번엔 let을 사용해보자
if(false){
let x = 'hello';
}
console.log(x); // ReferenceError x is no definded
let을 사용하면 선언한 변수는 블록안에서만 유효하게 된다. 따라서 블록 밖에서 접근했더니 RefenceError 를 발생시켰다. const 역시 마찬가지로 블록스코프를 따른다 .const 와 let의 차이점은 const 는 상수로 값을 할당한다는 점이다. 따라서 값을 변경시키려고 하면 에러를 발생시킨다 .
const x = 'hello World';
x = 'show me the money' // uncaught TypeError : Assignment to constant variale.
하지만 이는 정확한 표현이 아니다 const와 바인딩 된 값은 상수가 되지만 할당된 값은 변경이 가능하다. 따라서 아래와 같은 코드도 정상적으로 동작한다.
const x = {};
// x = null; 에러
x.a = 'Apple';
x.b = 'Banana';
화살표 함수 ( Arrow Function)
Es6 에서 소개된 가장 인상적인 기능중 하나는 화살표 함수의 지원이다. 화살표 함수는 함수 정의를 보다 간결한 구문으로 콜백을 정의할때 특히 유용하다. 아래는 고전적인 필터링의 예시이다.,
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const even = numbers.filter(function (x) {
return x % 2 === 0;
})
아래와 코드이다. 화살표 함수로 작성한 코드
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const even = numbers.filter(x => x % 2 === 0);
function 키워드가 사라지고 함수의 인자 다음에 => 가 나오고 본문을 작성한다. 본문이 return 문 하나만 있을 경우 {} 는 생략이 가능하다.
화살표 함수의 가장 중요한 기능중 하나는 어휘 범위 로 바인딩 된다는 점이다. 즉 , 화살표 함수 내부의 this 값은 부모의 블록의 this 값과 같다. 아래의 예시는 this 값의 범위가 달라 원하는 대로 동작하지 않는 경우이다. 일반적으로 function 키워드는 각각이 새로운 this 값을 생성하기 때문이다.
function DelayGreeter(name){
this.name =name;
}
DelayGreeter.prototype.greet = function(){
setTimeout(function cb() {
console.log('Hello' + this.name);
},1000);
}
const greeter = new DelayGreeter('World');
greeter.greet(); // Hello undefined
그리고 위의 코드가 원하는대로 동작하게 하기 위해선 bind 를 사용해 this 값을 바인딩 해주어야 했다.
setTimeout((funcion cb() {
console.log('Hello' + this.name);
}).bind(this),1000);
그러나 화살표함수는 부모 블록의 this 와 바인딩이 자동으로 이루어지기 때문에 훨씬 간결하게 문제를 해결할수있다.
setTimeout(() => console.log('Hello' + this.name), 1000);
클래스 구문
ES6에서 클래스 구문이 도입되었다. 하지만 자바스크립트 런타임에 의해 내부적으로 객체가 관리되는 방식이 바뀐 것은 아니어서 여전히 프로토타입을 통해 속성과 함수를 상속한다는 점이 중요하다.
클래스 구문의 도임은 개발자에게 유용하고 뛰어난 가독성을 제공하며 ,단지 편의를 위한 것이다. 아래는 전통적인 프로토타입 기반의 Person 함수를 보여준다.
function Person( name, age, job){
this.name = name;
this.age=age;
this.job = job;
}
Person.prototype.getAgeAndName = function () {
return this.age + ' ' + this.name;
}
Person.older = function (person1, person2 ){
return person1.age >= person2.age ? person 1: person2;
}
const seo = new Person('SDS' , 30 , 'Programmer');
const ahn = new Person ('AHY', 28 , 'Staff') ;
console.log(seo.getAgeName());
console.log(Person.older(seo,ahn));
다음은 클래스 구문을 동해 작성한 동일한 코드이다.
class Person {
constructor (name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
getAgeAndName () {
return this.age + ' ' + this.name;
}
static older (person1, person2) {
return person1.age >= person2.age ? person1 : person2;
}
}
const seo = new Person('SDS', 30, 'Programmer');
const ahn = new Person('AHY', 28, 'Staff');
console.log(seo.getAgeAndName());
console.log(Person.older(seo, ahn));
클래스 구문을 통해 표현하면 훨씬 이해하기 쉽고 간결하다. 생성자를 명시적으로 기술하고 있고 , static 메서드를 선언할 수도 있다. 클래스 구문의 유용한 점은 extends 키워드와 super 키워드를 통해 Person 프로토 타입을 확장을 할수 있다는 것이다 . 아래와 같이 확장이 가능하다.
class PersonWithCar extends Person{
constructor (name, age, job, car) {
super(name, age, job);
this.car = car;
}
getAgeAndName () {
return this.age + ' ' + this.name + ' ' + this.car;
}
}
const kwon = new PersonWithCar('KMS', 30, 'Technician', 'K5');
console.log(kwon.getAgeAndName ());
여기서 주목해야 할 점은 다른 객체지향언어에서 일반적으로 나타나는 모습과 굉장히 유사하다는 점이다.
확장하고자 하는 클래스로부터 새로운 클래스를 선언하고 ,super 키워드를 사용하여 부모 생성자를 호출하는 새로운 생성자를 정의 하였으며 , 기존의 메서드를 오버라이딩 했다.
1.속성과 할당하고자 하는 값이 일치하는 경우 생략 가능하다.
const a = 'Apple';
const b = 'Banana';
const es5 = { a: a, b: b };
const es6 = { a, b};
const es5 = {
age: 30,
getAge: function () {
return this.age;
}
}
const es6 = {
age: 30,
getAge () {
return this.age;
}
}
3.객체의 속성을 동적으로 할당할 수 있다.
const name = 'SDS';
const person = {
[name + "'s Age"]: 30
}
console.log(person) // { "SDS's Age": 30 }
4.새로운 getter, setter 구문이 추가 되었다.
참고로 set함수는 get함수가 반환하는 값을 반환하도록 되어있다.
const person = {
name: 'George',
surname: 'Boole',
get fullname () {
return this.name + ' ' + this.surname;
},
set fullname (fullname) {
let parts = fullname.split(' ');
this.name = parts[0];
this.surname = parts[1];
}
}
console.log(person.fullname); // George Boole
console.log(person.fullname = 'Alan Turing'); // Alan Turing
console.log(person.name); // Alan
간단하다 . 빽틱 (``)으로 둘러싸고 원하는 문자열을 입력하게 된다. ${} 안에 넣고 싶은 변수를 넣으면 알아서 해당 위치에 매핑된다.
const hello = 'Hello';
const to = 'Everybody!';
console.log(`${hello} ${to}`);
배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 표현식이다.
배열 구조 분해
let foo = ["one", "two", "three"];
let [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
객체 구조 분해
let fruit = {
a: 'Apple',
b: 'Banana',
}
let { a, b } = fruit;
console.log(a); // 'Apple'
console.log(b); // 'Banana'