Beautiful JavaScript
ECMAScript 2015 / ES6
code.ryan.lee@gmail.com
Introduction
그럼에도 불구하고
-
cross browsing
-
transpiler
2009.12 ES5
2015.06 ES6
2016.06 ES7
2017.06 ES8
Introduction
아름다운 코드에 대한 열망
Introduction
precondition
Server-side JavaScirpt
Node.js
Background
JavaScript Engine
JavaScript로 작성된 코드를 해석하고 실행하는 인터프리터
console.log('hi');
어휘 분석
구문 분석 실행
Background
V8 Engine
Open source high-performance JavaScript engine by Google.
Written in C++
Background
Overall
- Engine: JavaScript로 작성된 스크립트를 기계 실행 가능하게 변경. 구문 분석 및 JIT 컴파일
- Runtime : 실행 중 프로그램에서 사용할 수있는 기본 라이브러리를 제공
Chrome and Node.js therefore share the same engine (Google’s V8), but they have different runtime (execution) environments.
window.alert('hi');
console.log(__dirname);
Beautiful Code
Short
Simple
Small
Stupid
Destructuring Assignment
ES5
var name = req.body.name
var age = req.body.age
var email = req.body.email
ES6
const {name, age, email} = req.body
Object Initialize
ES5
var name = 'hak'
var age = 27
var email = 'code.ryan.lee@gmail.com'
var datas = {
name: name,
age: age,
email: email
}
ES6
let name = 'hak'
let age = 27
let email = 'code.ryan.lee@gmail.com'
let datas = {name, age, email}
let datas2 = {username: name, age, email}
Template Literals
ES5
var username = req.body.username
if ( !username ) {
throw "'username' must required. Your input: " + username + "."
}
ES6
let {username} = req.body
if ( !username ) {
throw `'username' must required. Your input: ${username}.`
}
Default Parameters
ES5
var greeting = function(username, date, message) {
username = typeof username !== 'undefined' ? username : 'anonymous'
date = typeof date !== 'undefined' ? date : new Date()
message = typeof message !== 'undefined' ? message : 'hello'
return message + ' ' + username + ' at ' + date
}
ES6
const greeting = (username='anonymous', date=new Date(), message='hello') => {
return `${message} ${username} at ${date}`
}
Promise - Co - async/await
Callback Hell!!
callback -> async.js -> promise -> generator -> async/await
Now
Future
Callback
function time() {
setTimeout(function() {
return 'time!';
}, 1000);
}
var a = time(); // undefined
function time(callback) {
setTimeout(function() {
callback('time!');
}, 1000);
}
var a;
time(function(r) {
a = r;
});
Promise
Promise is built-in from ECMAScript 2015
const getName = (user_id) => {
return new Promise( (resolve, reject) => {
if ( !user_id ) {
return reject('user_id must be required.')
}
Model.select('table_users', user_id)
.then( result => {
resolve( result.username )
})
.catch( err => {
reject( err )
})
});
}
Rule : Make all asynchronous functions return Promise!
Generator - Co
Generator was added from ECMAScript 2015
const gen = (a, b, c, conn) => {
return new Promise( (resolve, reject) => {
return co(function* () {
try {
yield async1(a);
yield async2(b);
yield async3(c);
resolve(true);
} catch (e) {
reject(e);
} finally {
conn = null;
}
});
});
};
The yieldable objects currently supported are: Promise
async/await
async/await was added from ECMAScript 2017
When an async function is called, it returns a Promise.
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function add1(x) {
const a = await resolveAfter2Seconds(20);
const b = await resolveAfter2Seconds(30);
return x + a + b;
}
add1(10).then(v => {
console.log(v); // prints 60 after 4 seconds.
});
async/await
Big picture
// ES6 - Generator
const bigPicture = function* () {
let awesome = yield beautiful()
}
// ES8 - async/await
const bigPicture = async function() {
let awesome = await beautiful()
}
Beautifier
function f(){
fs.readFile('one.js', function(e1, d1) {
fs.readFile('two.js', function(e2, d2) {
fs.readFile('three.js', function(e3, d3) {
// Done!!
});
});
});
}
function f(){
fun1.then(function(d1){
return func2;
}, function(e1){
// error func1
}).then(function(d2){
return func3;
}, function(e2){
// error func2
}).then(function(d3){
// Done!!
}, function(e3){
// error func3
});
}
function f(){
co(function* () {
try {
let d1 = yield fun1();
let d2 = yield fun2();
let d3 = yield fun3();
} catch (e) {
}
});
}
async function f() {
try {
let d1 = await fun1();
let d2 = await fun2();
let d3 = await fun3();
} catch (e) {
}
}
callback
promise
generator
async/await
if-else
const error = (name, age, email) => {
if ( name && name.length > 3 ) {
// something
// ...
if ( age < 30 ) {
// something
// ...
if ( /이메일정규식/.test(email) ) {
// something
// ...
return true
} else {
return false
}
} else {
return false
}
} else {
return false
}
}
const error = (name, age, email) => {
if ( !name || name.length < 4 ) {
return false
}
// something
// ...
if ( age >= 30 ) {
return false
}
// something
// ...
if ( !/이메일정규식/.test(email) ) {
return false
}
// something
// ...
return true
}
Bad case - Non Error First
Good case - Error First
if-else
const makeError = (a, b) => {
return new Promise( (resolve, reject) => {
return co(function* () {
try {
const val1 = yield async1(a);
if ( val1 > 10 ) throw 'Error!';
const val2 = yield async2(b);
resolve( val1 + val2 );
} catch (e) {
reject(e); // 'Error!'
}
});
});
};
underscore.js
or lodash.js
const users = [
{
name: 'lsh',
age: 27,
job: 'Programmer'
},
{
name: 'Kendrick',
age: 30,
job: 'Rapper'
},
{
name: 'statham',
age: 50,
job: 'Actor'
}
]
_.pluck(users, 'name');
// =>['lsh', 'Kendrick', 'statham']
_.pluck(users, 'job');
// =>['Programmer', 'Rapper', 'Actor']
underscore.js
or lodash.js
_.groupBy(['one', 'two', 'three'], 'length');
=> {3: ["one", "two"], 5: ["three"]}
_.contains([1, 2, 3], 3);
=> true
_.compact([0, 1, false, 2, '', 3]);
=> [1, 2, 3]
_.pairs({one: 1, two: 2, three: 3});
=> [["one", 1], ["two", 2], ["three", 3]]
_.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age');
=> {name: 'moe', age: 50}
_.omit({name: 'moe', age: 50, userid: 'moe1'}, 'userid');
=> {name: 'moe', age: 50}
Conclusion
태양처럼 너는 밝고 아리따워
여름처럼 너는 밝고 아리따워
beautiful beautiful
찾아봐요 당신만의 아리따움