From bb1d2bdf5e6f14af2c3f8d125893395e1859b284 Mon Sep 17 00:00:00 2001 From: seognil LC Date: Tue, 11 Feb 2020 23:00:40 +0800 Subject: [PATCH] feat(add): js sugar --- js/syntactic-sugar/src/async.ts | 50 +++++++++++ js/syntactic-sugar/src/decorator.ts | 82 ++++++++++++++++++ js/syntactic-sugar/src/syntax-es6.ts | 119 +++++++++++++++++++++++++++ js/syntactic-sugar/src/syntax-ts.ts | 116 ++++++++++++++++++++++++++ js/syntactic-sugar/src/trick.ts | 92 +++++++++++++++++++++ js/syntactic-sugar/tsconfig.json | 12 +++ 6 files changed, 471 insertions(+) create mode 100644 js/syntactic-sugar/src/async.ts create mode 100644 js/syntactic-sugar/src/decorator.ts create mode 100644 js/syntactic-sugar/src/syntax-es6.ts create mode 100644 js/syntactic-sugar/src/syntax-ts.ts create mode 100644 js/syntactic-sugar/src/trick.ts create mode 100644 js/syntactic-sugar/tsconfig.json diff --git a/js/syntactic-sugar/src/async.ts b/js/syntactic-sugar/src/async.ts new file mode 100644 index 0000000..a7eb0f4 --- /dev/null +++ b/js/syntactic-sugar/src/async.ts @@ -0,0 +1,50 @@ +// * ------------------------------------------------ async await + +{ + const timeout = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms)); + + const print = async () => { + await timeout(100); + console.log('Async Hello'); + await timeout(200); + console.log('Async Again'); + }; + + print(); +} + +// * ------------------------------------------------ Promise + +{ + const timeout = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + + const print = () => { + timeout(100) + .then(() => { + console.log('Promise Hello'); + }) + .then(() => timeout(200)) + .then(() => { + console.log('Promise Again'); + }); + }; + + print(); +} + +// * ------------------------------------------------ Callback + +{ + const timeout = (ms, callback) => setTimeout(callback, ms); + + const print = () => { + timeout(100, () => { + console.log('Callback Hello'); + timeout(200, () => { + console.log('Callback Again'); + }); + }); + }; + + print(); +} diff --git a/js/syntactic-sugar/src/decorator.ts b/js/syntactic-sugar/src/decorator.ts new file mode 100644 index 0000000..bcaf5d3 --- /dev/null +++ b/js/syntactic-sugar/src/decorator.ts @@ -0,0 +1,82 @@ +{ + // * ---------------- declaration + + function log(target, name, descriptor) { + var oldValue = descriptor.value; + + descriptor.value = function() { + console.log(`Calling ${name} with`, arguments); + const result = oldValue.apply(this, arguments); + console.log(`Result is ${result}`); + return result; + }; + + return descriptor; + } + + // * ---------------- usage + + class Tool { + @log + add(a, b) { + console.log(this); + return a + b; + } + } + + console.log(new Tool().add(1, 2)); +} + +// Calling add with [Arguments] { '0': 1, '1': 2 } +// Tool {} +// Result is 3 +// 3 + +// * ------------------------------------------------ alternative + +{ + // * ---------------- HOF + + const log = function(fn) { + return function(...args) { + console.log(`Calling ${fn.name} with`, arguments); + const result = fn.apply(this, args); + console.log(`Result is ${result}`); + return result; + }; + }; + + // * ---------------- usage + + class Tool { + add = log(function add(a, b) { + console.log(this); + return a + b; + }); + } + + console.log(new Tool().add(1, 2)); +} + +// * ------------------------------------------------ composition + +{ + // * ---------------- HOF + + const withLog = function(fn) { + return function(...args) { + console.log(`Calling ${fn.name} with`, arguments); + const result = fn.apply(this, args); + console.log(`Result is ${result}`); + return result; + }; + }; + + // * ---------------- usage + + const add = (a, b) => a + b; + + const addWithLog = withLog(add); + + console.log(addWithLog(1, 2)); +} diff --git a/js/syntactic-sugar/src/syntax-es6.ts b/js/syntactic-sugar/src/syntax-es6.ts new file mode 100644 index 0000000..14fe72c --- /dev/null +++ b/js/syntactic-sugar/src/syntax-es6.ts @@ -0,0 +1,119 @@ +// * ------------------------------------------------ for of + +{ + const arr = [1, 2, 3]; + + for (const val of arr) { + console.log(val); + } +} + +// * ---------------- for in + +{ + const arr = [1, 2, 3]; + + for (const key in arr) { + const val = arr[key]; + console.log(val); + } +} + +// * ------------------------------------------------ string + +{ + const language = 'JavaScript'; + + const str6 = `Hello ${language}`; + console.log(str6); +} + +// * ---------------- in ES5 + +{ + var language = 'JavaScript'; + + var str5 = 'Hello' + ' ' + language; + console.log(str5); +} + +// * ------------------------------------------------ array function + +{ + const arrFn = (a) => a + 1; + console.log(arrFn(6)); +} + +// * ---------------- in ES5 + +{ + function fnFn(a) { + return a + 1; + } + console.log(fnFn(6)); +} + +// * ------------------------------------------------ class + +{ + class Class6 { + val; + constructor(val) { + this.val = val; + } + log() { + console.log(this.val); + } + } + new Class6('hello').log(); +} + +// * ---------------- in ES5 + +{ + function Class5(val) { + this.val = val; + } + Class5.prototype.log = function() { + console.log(this.val); + }; + + new Class5('hello').log(); +} + +// * ------------------------------------------------ destructing + +{ + const arr = [1, 2]; + const [a, b] = arr; + + const obj = { c: 3, d: 4, e: 5 }; + const { c, ...d } = obj; + + const arr2 = [6, 7, 8]; + const [e, ...f] = arr2; + + console.log(a, b, c, d, e, f); +} + +// * ---------------- in ES5 + +{ + var arr = [1, 2]; + var a = arr[0]; + var b = arr[1]; + + var obj = { c: 3, d: 4, e: 5 }; + var c = obj.c; + + var d = {}; + for (var k in obj) { + if (k !== 'c') d[k] = obj[k]; + } + + var arr2 = [6, 7, 8]; + var e = arr2[0]; + var f = arr2.slice(1); + + console.log(a, b, c, d, e, f); +} diff --git a/js/syntactic-sugar/src/syntax-ts.ts b/js/syntactic-sugar/src/syntax-ts.ts new file mode 100644 index 0000000..7006b19 --- /dev/null +++ b/js/syntactic-sugar/src/syntax-ts.ts @@ -0,0 +1,116 @@ +// * ------------------------------------------------ Optional Chaining + +{ + const data = { bar: { baz: console.log } }; + + type validData = typeof data | null; + + const foo: validData = Math.random() ? data : null; + + const x = foo?.bar?.baz(); + + console.log('x is', x); +} + +// * ---------------- alternative + +{ + const data = { bar: { baz: console.log } }; + + type validData = typeof data | null; + + const foo: validData = Math.random() ? data : null; + + const x = + foo === null || foo === undefined + ? undefined + : foo.bar === null || foo.bar === undefined + ? undefined + : foo.bar.baz(); + + console.log('x is', x); +} + +// * ------------------------------------------------ Non-null assertion operator + +{ + interface Entity { + name: string; + } + + const validOrThrow = (e) => { + if (!e) throw 'your value is empty'; + }; + + const process = (e?: Entity) => { + validOrThrow(e); + + const name = e!.name; + console.log(name); + }; + + process({ name: 'Mick' }); +} + +{ + interface Entity { + name: string; + } + + const validOrThrow = (e) => { + if (!e) throw 'your value is empty'; + }; + + const process = (e?: Entity) => { + validOrThrow(e); + + const name = e !== undefined && e.name; + console.log(name); + }; + + process({ name: 'Mick' }); +} + +// * ------------------------------------------------ Nullish Coalescing + +{ + const foo = null; + const bar = () => 'John'; + + const x = foo ?? bar(); + + console.log('x is', x); +} + +// * ---------------- alternative + +{ + const foo = null; + const bar = () => 'John'; + + const x = foo !== null && foo !== undefined ? foo : bar(); + + console.log('x is', x); +} + +// * ------------------------------------------------ overload + +{ + function simpleAdd(a: number): (b: number) => number; + function simpleAdd(a: number, b: number): number; + function simpleAdd(a, b?) { + if (b === undefined) return (b) => a + b; + return a + b; + } + + const result = simpleAdd(1, 2); + console.log(result); + + const semiAdd = simpleAdd(3); + const result2 = semiAdd(4); + console.log(result2); +} + +// * ------------------------------------------------ Pattern matching + +// * not support diff --git a/js/syntactic-sugar/src/trick.ts b/js/syntactic-sugar/src/trick.ts new file mode 100644 index 0000000..cf96936 --- /dev/null +++ b/js/syntactic-sugar/src/trick.ts @@ -0,0 +1,92 @@ +// * ------------------------------------------------ ternary condition operator + +{ + const name: string = 'John'; + + const msg = name === 'admin' ? 'name is invalid' : 'name is valid'; + + console.log(msg); +} + +// * ---------------- alternative + +{ + const name: string = 'John'; + + let msg; + if (name === 'admin') { + msg = 'name is invalid'; + } else { + msg = 'name is valid'; + } + + console.log(msg); +} + +// * ------------------------------------------------ short-circuit evaluation + +{ + const alias = null; + const getNickName = () => 'John'; + const getUserName = () => 'User_John'; + + const result = alias || getNickName() || getUserName(); + + result && console.log(result); +} + +// * ---------------- alternative + +{ + const alias = null; + const getNickName = () => 'John'; + const getUserName = () => 'User_John'; + + let result: string | null = alias; + if (!result) result = getNickName(); + if (!result) result = getUserName(); + + if (result) { + console.log(result); + } +} + +// * ------------------------------------------------ quick boolean + +{ + const name = 'John'; + + const isNameEmpty = !name; + const isNameNotEmpty = !!name; + + console.log(isNameEmpty, isNameNotEmpty); +} + +// * ---------------- alternative + +{ + const name: string = 'John'; + + const isNameEmpty = name !== ''; + const isNameNotEmpty = Boolean(name); + + console.log(isNameEmpty, isNameNotEmpty); +} + +// * ------------------------------------------------ quick Math.Round + +{ + const a = ~~2.7; + const b = ~~-2.7; + + console.log(a, b); +} + +// * ---------------- alternative + +{ + const a = Math.floor(2.7); + const b = Math.ceil(-2.7); + + console.log(a, b); +} diff --git a/js/syntactic-sugar/tsconfig.json b/js/syntactic-sugar/tsconfig.json new file mode 100644 index 0000000..24cf209 --- /dev/null +++ b/js/syntactic-sugar/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": [ + "ESNext", + "DOM" + ], + "jsx": "preserve", + "experimentalDecorators": true, + "strictNullChecks": true, + }, +} \ No newline at end of file