nullish 병합 연산자(nullish coalescing operator)??를 사용하면 짧은 문법으로 여러 피연산자 중 그 값이 ‘확정되어있는’ 변수를 찾을 수 있습니다.
a ?? b의 평가 결과는 다음과 같습니다.
a가null도 아니고undefined도 아니면a
그 외의 경우는b
nullish 병합 연산자??없이x = a ?? b와 동일한 동작을 하는 코드를 작성하면 다음과 같습니다.
x = (a !== null && a !== undefined) ? a : b;
비교 연산자와 논리 연산자만으로 nullish 병합 연산자와 같은 기능을 하는 코드를 작성하니 코드 길이가 길어지네요.
또 다른 예시를 살펴봅시다.firstName,lastName,nickName이란 변수에 사용자 이름이나 별명을 저장하는데, 사용자가 아무런 정보도 입력하지 않는 케이스도 허용한다고 해보겠습니다.
화면엔 세 변수 중 실제 값이 있는 변수의 값을 출력하는데, 세 변수 모두 값이 없다면 '익명의 사용자’가 출력되도록 해보죠.
이럴 때 nullish 병합 연산자??를 사용하면 값이 정해진 변수를 간편하게 찾아낼 수 있습니다.
let firstName = null;
let lastName = null;
let nickName = "바이올렛";
// null이나 undefined가 아닌 첫 번째 피연산자
alert(firstName ?? lastName ?? nickName ?? "익명의 사용자"); // 바이올렛
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Dates</h1>
<h2>The getTime() Method</h2>
<p>Calculate the number of years since January 1, 1970:</p>
<p id="demo"></p>
<p id="demo2"></p>
<script>
// Calculate milliseconds in a year
const minute = 1000 * 60;
const hour = minute * 60;
const day = hour * 24;
const year = day * 365;
// Divide Time with a year
const d = new Date();
let years = Math.round(d.getTime() / year);
document.getElementById("demo").innerHTML = years;
document.getElementById("demo2").innerHTML = d.getTime();
// 월은 0부터 시작하여 생일은 1995 년 1 월 10 일이됩니다.
var birthday = new Date(1994, 12, 10);
var copy = new Date();
copy.setTime(birthday.getTime());
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Dates</h1>
<p>Add zeros and colons to display the time:</p>
<p id="demo"></p>
<script>
function addZero(x,n) {
while (x.toString().length < n) {
x = "0" + x;
}
return x;
}
const d = new Date();
let h = addZero(d.getHours(), 2);
let m = addZero(d.getMinutes(), 2);
let s = addZero(d.getSeconds(), 2);
let ms = addZero(d.getMilliseconds(), 3);
let time = h + ":" + m + ":" + s + ":" + ms;
document.getElementById("demo").innerHTML = time;
</script>
</body>
</html>
Date.getTime()는 UTC 시간을 millisecond로 리턴합니다. UTC는1970/01/01를 0초로 지금까지 흐른 시간을 표현한 것입니다. millisecond이기 때문에 비교 연산자를 이용하여 크기를 비교할 수 있고, 또한 동등 연산자로 비교할 수도 있습니다.
ES6(ECMAScript 표준의 6번째 에디션, ECMAScript2015)에 대한 이야기를 하기 전에 자바스크립트와ECMAScript에 대한 것부터 간략히 소개한다.
넷스케이프(Netscape)에서 1995년 개발한 자바스크립트(javascript)는 웹 브라우저에서 동적인 기능을 제공하기 위한 언어다. 현재는 대부분의 브라우저에서 이 언어를 제공하고 있다. 그런데 표준 규격없이 여러 브라우저에서 독자적인 특성이 추가되면서 호환성 문제가 발생하기 시작했다. 이에 ECMA 국제 기구에서 “ECMAScript Standard”라는 표준을 만들게 되었다. 정확히 이야기 하자면 현재의 자바스크립트는 ECMAScript와 BOM(Browser Object Model)와 DOM(Document Object Model)을 포괄하는 개념이다.
개별적인 설명에 앞서 개발자가 필히 알아야 할 ES6 10가지 기능을 나열하자면 아래와 같다.
기본 매개 변수 (Default Parameters)
템플릿 리터럴 (Template Literals)
멀티 라인 문자열 (Multi-line Strings)
비구조화 할당 (Destructuring Assignment)
향상된 객체 리터럴 (Enhanced Object Literals)
화살표 함수 (Arrow Functions)
Promises
블록 범위 생성자 Let 및 Const (Block-Scoped Constructs Let and Const)
클래스 (Classes)
모듈 (Modules)
1. 기본 매개 변수 (Default Parameters)
var link = function (height, color, url) {
var height = height || 50
var color = color || 'red'
var url = url || 'http://azat.co'
...
}
함수에 넘겨주는 인자값에 대한 default 처리를 위해 위와 같이 처리 했었다면 ES6에서는 아래와 같이 간단히 처리할 수 있다.
var link = function(height = 50, color = 'red', url = 'http://azat.co') {
...
}
단, 주의해야 할 점이 있다. 인자값으로 0 또는 false가 입력될 때 두 예시의 결과는 다르다. ES5에서는||처리 시 0 또는 false 값이 입력 되어도 거짓이 되므로 기본값으로 대체된다. 하지만 ES6의 기본 매개 변수를 사용하면 undefined 를 제외한 입력된 모든 값(0, false, null 등)을 인정한다.
2. 템플릿 리터럴 (Template Literals)
ES5에서는 아래와 같이 문자열을 처리해야 했다.
var name = 'Your name is ' + first + ' ' + last + '.'
var url = 'http://localhost:3000/api/messages/' + id
하지만 ES6에서는 템플릿 리터럴을 제공하므로 "`" (back-ticked) 문자열 안에${NAME}라는 새로운 구문을 사용해서 아래와 같이 간단히 처리할 수 있다.
var name = `Your name is ${first} ${last}.`
var url = `http://localhost:3000/api/messages/${id}`
3. 멀티 라인 문자열 (Multi-line Strings)
ES5에서는 멀티 라인 문자열을 처리하기 위해 아래와 같은 방법들을 사용해야 했다.
var roadPoem = 'Then took the other, as just as fair,\n\t'
+ 'And having perhaps the better claim\n\t'
+ 'Because it was grassy and wanted wear,\n\t'
+ 'Though as for that the passing there\n\t'
+ 'Had worn them really about the same,\n\t'
var fourAgreements = 'You have the right to be you.\n\
You can only be you when you do your best.'
하지만 ES6에서는 "`" (back-ticked) 문자열을 이용해서 아래와 같이 간단히 처리할 수 있다.
var roadPoem = `Then took the other, as just as fair,
And having perhaps the better claim
Because it was grassy and wanted wear,
Though as for that the passing there
Had worn them really about the same,`
var fourAgreements = `You have the right to be you.
You can only be you when you do your best.`
4. 비구조화 할당 (Destructuring Assignment)
ES5에서는 구조화된 데이터를 변수로 받기 위해 아래와 같이 처리해야 했다.
// browser
var data = $('body').data(), // data has properties house and mouse
house = data.house,
mouse = data.mouse
// Node.js
var jsonMiddleware = require('body-parser').json
var body = req.body, // body has username and password
username = body.username,
password = body.password
하지만 ES6에서는 비구조화 할당을 사용해 아래와 같이 처리할 수 있다.
var {house, mouse} = $('body').data() // we'll get house and mouse variables
var {jsonMiddleware} = require('body-parser')
var {username, password} = req.body
주의할 점은 var로 할당하려는 변수명과 구조화된 데이터의 property명이 같아야 한다. 또한 구조화된 데이터가 아니라 배열의 경우{}대신[]를 사용해서 위와 유사하게 사용할 수 있다.
accountServiceES5ObjectCreate와 accountServiceES5는 동일하게 사용할 수 있으나 다른 구조를 가진다. accountServiceES5ObjectCreate는 accountServiceES5와 다르게__proto__에port와url속성을 가진 객체를 담고 있다.
화살표 함수가 한 줄의 명령문과 함께 사용되면 표현식이 되어 명령문의 결과를 암시적으로 반환한다.
ES5에서의 처리 예시.
var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map(function (value) {
return "ID is " + value // explicit return
});
ES6에서의 처리 예시.
var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map(value => `ID is ${value}`) // implicit return
여러 개의 인자를 사용하는 경우는 변수 목록을()로 감싸줘야 한다.
ES5에서의 처리 예시.
var ids = ['5632953c4e345e145fdf2df8', '563295464e345e145fdf2df9'];
var messages = ids.map(function (value, index, list) {
return 'ID of ' + index + ' element is ' + value + ' ' // explicit return
});
ES6에서의 처리 예시.
var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map((value, index, list) => `ID of ${index} element is ${value} `) // implicit return
또한 본문을 괄호로 감싸 객체 표현식을 반환할 수 있으며...을 이용해 가변 파라미터를 사용할 수도 있다.
var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map((value, index, ...abc) => ({v:value, i:index, a:abc}))
8. 블록 범위 생성자 Let 및 Const (Block-Scoped Constructs Let and Const)
let과 const는 중괄호("{}")로 정의된 블록으로 유효 범위(스코프)를 지정하는 새로운 var이다. 단, let은 변수를 const는 상수를 선언한다.
function calculateTotalAmount (vip) {
var amount = 0
if (vip) {
var amount = 1
}
{ // more crazy blocks!
var amount = 100
{
var amount = 1000
}
}
return amount
}
console.log(calculateTotalAmount(true))
위 예시의 결과는 1000 이다. var는 전역 또는 함수 내부로 유효 범위를 갖기 때문에 예시에 사용된 함수 내부의 "{}" 들은 아무런 역할을 하지 못한다. 아래는 위 예시에서 var를 let으로 바꾼 ES6 예시다.
function calculateTotalAmount (vip) {
var amount = 0 // probably should also be let, but you can mix var and let
if (vip) {
let amount = 1 // first amount is still 0
}
{ // more crazy blocks!
let amount = 100 // first amount is still 0
{
let amount = 1000 // first amount is still 0
}
}
return amount
}
console.log(calculateTotalAmount(true))
이 예시의 결과는 0 이다. let 으로 선언된 변수는 "{}" 블록 내부로 유효 범위가 한정되므로 100, 1000으로 할당된 변수는 해당 블록 내부에서만 유효하기 때문이다.if블록 내부에서 let으로 선언된 amount 또한 해당if블록 내에서만 유효하므로 아무런 변경이 일어나지 않는다.
아래의 예시는 const를 사용한 예시다. const는 상수를 선언하는 것으로 여러번 선언될 수 없지만 let과 같이 블록 내부로 유효 범위가 한정되므로 아래의 예시는 오류가 발생하지 않는다.
ES6는 확정되었지만 아직 모든 브라우저에서 완전하게 지원되지 않는다. 따라서 지금 당장 ES6 사용하고 싶다면Babel과 같은 컴파일러를 사용해야 한다. Babel은 독립 실행형 도구로 실행하거나 빌드 시스템에서 사용할 수 있다.Grunt,Gulp및Webpack용 Babel 플러그인이 있다.