ES6 특징

양세희·2022년 5월 29일
0
post-thumbnail
post-custom-banner

let과 const

전통적으로 자바스크립트는 함수 스코프와 전역 스코프만을 지원하여 변수의 생명주기 및 접근을 제어해왔다.

하지만 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 not defined

let을 사용하면 선언한 변수는 블록 안에서만 유효하게 된다. 따라서 블록 밖에서 접근했더니 ReferenceError를 발생시켰다. const도 마찬가지로 블록 스코프를 따른다. const와 let의 차이점은 const는 상수로 값을 할당한다는 점이다. 따라서 갑승ㄹ 변경시키려고 하면 에러를 발생시킨다.

const x = 'Hello World';
x = 'Bye World'; // Uncaught TypeError: Assignment to constant variable.

하지만 이는 정확한 표현이 아니다. const와 바인딩 된 값은 상수가 되지만 할당된 값으 변경이 가능하다. 따라서 아래와 같은 코드도 정상적으로 동작한다.

const x = {};
// x = null; 에러
x.a = 'Apple';
x.b = 'Grape';

화살표 함수 (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문 하나만 있을 경우 {}는 생략 가능하다. 또한 함수의 힌자가 하나일 경우 () 역시 생략 가능하다.

화살표 함수의 중요한 기능 중에 하나는 어휘 범위(Lexical Scope)로 바인딩 된다는 것이다. 즉, 화살표 함수 내부의 this 값은 부모 블록의 this 값과 같다.

아래의 예시는 this 값의 범위가 달라 원하는 대로 동작하지 않는 경우이다. 일반적으로 function 키워드는 각각 새로운 this 값을 생성하기 때문이다.

function DelayedGreeter(name) {
    this.name = name;
}

DelayedGreeter.prototype.greet = function () {
    setTimeout(function cd() {
        console.log('Hello ' + this.name);
     }, 1000);
}

const greeter = new DelayedGreeter('World');
greeter.greet(); // Hello undefined

그리고 위의 코드가 원하는대로 동작하게 하기 위해서는 bind를 사용해 this의 값을 바인딩 해줘야 한다.

setTimeout((function 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;
}

const seo = new Person('SDS', 30, 'Programmer');
const yang = new Person('YSH', 28, 'Staff');

console.log(seo.getAgeAndName());
console.log(Person.older(seo, yang));

다음은 클래스 구문을 통해 작성한 동일한 코드이다.

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 yang = new Person('YSH', 28, 'Staff');

console.log(seo.getAgeAndName());
console.log(Person.older(seo, yang));

클래스 구문을 통해 표현하면 훨씬 이해하기 쉽고 간결하다. 생성자를 명시적으로 기술하고 있고, 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('KHS', 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};
  1. 함수를 속성으로 가지는 경우 function 키워드는 생략 가능하다.
	const  es5 = {
    	age: 30,
        getAge: function () {
        	return this.age;
        }
    }
    
    const es6 = {
    	age: 30,
        getAge() {
        	return this.age;
       }
   }
  1. 객체의 속성을 동적으로 할당할 수 있다.
	const name = 'SDS'
    const person = {
    	[name + "'s Age"]: 30
    }
    console.log(person) // {"SDS's Age": 30}
  1. 새로운 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(persoon.fullname); // George Boole
console.log(person.fullname = 'Alan Turing'); // Alan Turing
console.log(person.name); // Alan

Template 표기법

백틱으로 둘러싸고 원하는 문자열을 입력하면 된다. ${} 안에 넣고 싶은 변수를 넣으면 알아서 해당 위치에 매핑된다.

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 } = fruitl
console.log(a); // 'Apple'
console.log(b); // 'Banana'
post-custom-banner

0개의 댓글