[JS] ES5와 ES6 뭐가 다를까?

ES5와 ES6를 비교 할겸 ES6를 사용할때 자주 쓰이는 부분만 정리해보았습니다.

Immutable varibale인 Const 변수(상수 변수)를 지원합니다.(블록-스코프 변수)

const PI = 3.141592
console.log(PI) // 3.141592

기존의 함수-스코프였던 변수와 다르게 Hoisting 없는 블록-스코프 변수를 지원합니다.

// ES5
console.log('for loop start')
for(var i=0; i<10; i++) {
    console.log('i : ' + i)
}
console.log('for loop end i : ' + i) // for loop end i : 10

function counter() {
    for(var j=0; j<10; j++) {
        console.log('j : ', j)
    }
}
counter()
console.log('j : ', j) // j is not defined

// ES6
console.log('for loop start')
for(let i=0; i<10; i++) {
    console.log('i : ' + i)
}
console.log('for loop end i : ' + i) // j is not defined

function counter() {
    for(let j=0; j<10; j++) {
        console.log('j : ', j)
    }
}
counter()
console.log('j : ',j) // j is not defined

또한 var 변수는 재선언,재할당이 가능하지만 let 변수는 재선언이 불가능합니다 (const 변수는 immutable variable이므로 재할당도 불가능)

var a = 'foo'
var a = 'bar'

// hoisting으로 ReferenceError가 나지않는다.
b = 'foo'
var b

let c = 'foo'
let c = 'bar' // Uncaught SyntaxError: Identifier 'c' has already been declared
c = 'bar' // "bar"

const d = 'foo'
const d = 'bar' // Uncaught SyntaxError: Identifier 'd' has already been declared
d = 'bar' // Uncaught TypeError: Assignment to constant variable.

블록-스코프 함수 정의 방식 개선

// ES6
{
    function foo () { return 1 }
    console.log(foo()) // 1
    {
        function foo() { return 2 }
        console.log(foo()) // 2
    }
    console.log(foo()) // 1
}
// ES5
(function () {
    var foo = function () { return 1;}
    foo() === 1;
    (function () {
        var foo = function () { return 2; }
        foo() === 2;
    })();
    foo() === 1;
})();

functionreturn을 묶어 화살표 함수로 변형 가능합니다

// ES6
nums = evens.map((v,i) => v+i)
this.nums.forEach((v) => {
    if(v % 2 === 0)
        this.evens.push(v)
})
// ES5
nums = evens.map(function (v, i) { return v+i; });
var self = this;
this.nums.forEach(function (v) {
    if(v % 2 === 0)
        self.evens.push(v);
});

타 언어에서 사용 할 수 있었던 디폴트 파라미터가 지원됩니다.

// ES6
function foo (x, y=2, z=3) {
    return x + y + z
}
foo(1) // 6

// ES5
function foo (x, y, z) {
    if(y === undefined)
        y = 2;
    if(z === undefined)
        z = 3;
    return x + y + z;
};
foo(1); // 6

지정되지 않은 매개변수 집합을 하나의 변수에 담을 수 있습니다.

// ES6
function foo (x, y, ...a) {
    return (x * y) + a.length
}
foo(1, 2, "baz", true , 3, [2]) // 6

// ES5
function foo (x,y) {
    var a = Array.prototype.slice.call(arguments, 2);
    return (x * y) + a.length;
};
foo(1, 2, "baz", true , 3, [2]); // 6

2개 이상의 인수나 2개이상의 요소 또는 2개이상의 변수가 해당되는 곳에 확장 될 수 있도록 합니다.

function myFunc(x, y, z){}
// ES6
let params = [ "Foo", true, 2 ]
let others = [ 1, 2, ...params ] // [ 1, 2, "Foo" ,true, 2 ]
let str = "Bar"
let chars = [ ...str ] // [ "B", "a", "r"]
myFunc(1, 2, ...params);
// ES5
var params = [ "Foo", true, 2 ];
var others = [ 1, 2 ].concat(params); // [ 1, 2, "Foo" ,true, 2 ]
var str = "Bar";
var chars = str.split(""); // [ "B", "a", "r"]
myFunc.apply(null, [1, 2].concat(params));

문자열 다중 행 처리와 보간문자 처리를 할 수 있습니다.

// ES6
let user = { name : "Foo" }
let info = { id: "bar", email: "[email protected]"}
let userInfo = `Hello ${user.name}.
Your ID is ${info.id} 
and email is ${info.email}.`
// Hello Foo.
// Your ID is bar
// and email is [email protected]

// ES5
var user = { name : "Foo" }
var info = { id: "bar", email: "[email protected]"}
var userInfo = "Hello " + user.name + ".\n"+
"Your ID is " + info.id + "\n"
"and email is "+info.email+".";

공통 객체 속성 정의를 간결하게 할 수 있습니다.

// ES6
let x = 0, y = 0
obj = {x, y}

// ES5
var x = 0, y = 0;
obj = {x: x , y: y};

Object 프로퍼티 정의에 계산된 이름을 지원합니다

// ES6
let obj = {
    foo: "Bar",
    ["Baz" + myFunc() ]: 42
}

// ES5
var obj = {
    foo: "Bar"
};
obj["Baz" + myFunc() ] = 42;

일반적인 함수와 제너레이터 함수의 Object 프로퍼티 정의에 메소드를 표기할 수 있도록 지원합니다.

// ES6
obj = {
    foo (a, b) {},
    bar (x ,y) {},
    *baz (x, y) {}
}

// ES5
obj = {
    foo: function (a, b) {},
    bar : function (x, y) {},
    // baz : es5에서는 대체할 것이 없습니다.
}

값을 export/import로 모듈에 가져오거나 모듈로 내보낼 수 있습니다.

// ES6

// lib/math.js
export function sum (x ,y) { return x + y }
export var pi = 3.141592
// Foo.js
import * as math from "lib/math"
console.log("2pi = " + math.sum(math.pi, math.pi))
// Bar.js
import { sum, pi } from "lib/math"
console.log("2pi = " + sum(pi,pi))

//ES5
// lib/math.js
LibMath = {};
LibMath.sum = function (x ,y) { return x + y };
LibMath.pi = 3.141592;
// Foo.js
var math = LibMath;
console.log("2pi = " + math.sum(math.pi, math.pi));
// Bar.js
var sum = LibMath.sum, pi = LibMath.pi;
console.log("2pi = " + sum(pi,pi));

클래스를 지원합니다 (이외에도 상속, 오버로딩, 정적 클래스멤버, Getter/Setter를 지원합니다.)

// ES6
class Car {
    constuctor (id, x ,y) {
        this.id = id
        this.move(x,y)
    }
    move (x, y) {
        this.x = x
        this.y = y
    }
}

// ES5
var Car = function (id, x ,y) {
    this.id = id;
    this.move(x, y);
};
Car.prototype.move = function (x, y) {
    this.x = x;
    this.y = y;
}

비동기 처리 이후 동작을 순차적,또는 병렬로 진행하기 위해 사용하는 클래스. 기존 Callback Hell에서 벗어날 수 있도록 도와줍니다(잘 구현 했을 경우….)

// ES6
let _promise = () => {
    return new Promise((resolve,reject) => {
        if(success){
            resolve(value) // success
        } else {
            reject(reason)  // fail
        }
    })
}
_promise()
    .then(
        (res) => {
            //success일때 처리
            console.log(res)
        },
        (err) => {
            //reject 일때 처리
            console.error(err)
        }
    )
_promise()
    .then(...)
    .catch((err) => {
        console.error(err)
    })

여러개의 프로미스가 모두 완료 될때 실행하려면요?

let _promise1 = new Promise((resolve,reject) => {
        if(success){
            resolve(value) // success
        } else {
            reject(reason)  // fail
        }
    })
let _promise2 = new Promise((resolve,reject) => {
        if(success){
            resolve(value) // success
        } else {
            reject(reason)  // fail
        }
    })

Promise.all([_promise1, _promise2]).then(
    (res) => {
        // resolve 된 결과 처리
        console.log(res)
    },
    (err) => {
        // reject 된 결과 처리
        console.log(err)
    }
)

// OR

let _promise1 = () => {
    return new Promise((resolve,reject) => {
        if(success){
            resolve(value) // success
        } else {
            reject(reason)  // fail
        }
    })
}
let _promise2 = () => {
    return new Promise((resolve,reject) => {
        if(success){
            resolve(value) // success
        } else {
            reject(reason)  // fail
        }
    })
}

Promise.all([_promise1(), _promise2()]).then(
    (res) => {
        // resolve 된 결과 처리
        console.log(res)
    },
    (err) => {
        // reject 된 결과 처리
        console.log(err)
    }
)

참고자료