Clean Code with ES6 Default Parameters & Property Shorthands
์ด๊ฒ์ ์ ๊ฐ ๊ณต๋ถํ๋ฉด์ ๋ฒ์ญ์ ํ ๋ด์ฉ์
๋๋ค. ๋ฒ์ญ์ด ์ ๋ง ์๋ง์ด์ง๋ง ์ ๋ง ์์๋ณผ ์ ์์ผ๋ฉด ๋๋ค๊ณ ์๊ฐํด์ ^^ ํน์ ์๋ณธ์ ๋ณด์ ์ค์ญ์ด๋ ๋ ์ข์ ๋ฒ์ญ์ ์๋ ค์ฃผ์๋ฉด ๋ณ๊ฒฝํ๊ฒ ์ต๋๋ค. ๋ํ ๊ฐ์ธ ์ ์ธ๊ฒ์ด๊ธฐ ๋๋ฌธ์๊ณต์ ๋ ์ ํ์
จ์ผ๋ฉด ํฉ๋๋ค. ํน์ ๋ ๋ฒ์ญ์ ๋ณด์๊ณ ๋ฌธ์ ๋ฅผ ์ ์ ํ์๋ฉด ๋ฐ๋ก ์ญ์ ํ๋๋ก ํ๊ฒ ์ต๋๋ค.์๋ณธ : https://www.sitepoint.com/es6-default-parameters/
์ฐ๋ฆฌ์ ์ง์์ ๋น ๋ฅด๊ฒ ์ ์ ํ๊ฒ ํ๊ณ , ๋ค์ ๊ตฌ๋ฌธ์ ์ดํด๋ณด์. ๊ธฐ๋ณธ ํ๋ผ๋ฏธํฐ์ ๊ธฐ๋ณธ ๊ฐ์ผ๋ก ํจ์๋ฅผ ์ด๊ธฐํ ํ๋ ๊ฒ์ ์ฐ๋ฆฌ๋ ํ๋ฝํ๋ค. default๋ arguments๊ฐ omitted ์ด๊ฑฐ๋ undefined์ผ๋ ์ฌ์ฉ๋์ด ์ง๋ค. ์ด๊ฒ์ ์๋ฏธ์ null์ ์ ํจํ ๊ฐ์ด๋ค. ๊ธฐ๋ณธ ํ๋ผ๋ฏธํฐ๋ ์ซ์์์ ๋ค๋ฅธ ํจ์๊น์ง ํ ์ ์๋ค.
// Basic syntax function multiply (a, b = 2) { return a * b; } multiply(5); // 10 // Default parameters are also available to later default parameters function foo (num = 1, multi = multiply(num)) { return [num, multi]; } foo(); // [1, 2] foo(6); // [6, 12]
๊ธฐ๋ณธ ํจ์๋ฅผ ๋ง๋ค๊ณ , default parameters๊ฐ ๊ฐ๋ฐ์ ์๋์ ์ฝ๋์ ๋ ์ ๊ตฌ์ฑ ํ ์ ์๋ ๋ฐฉ๋ฒ์ ์
์ฆํด ๋ณด์
์ฐ๋ฆฌ์ ์์ ๋ฉ์๋๋ createElement()๋ฅผ ๋ถ๋ ค์ง๋ค. ๋ช๊ฐ์ง configuration arguments ๊ฐ์ง๊ณ , HTML elements๋ฅผ returns ํ๋ค. API๋ ์ด์ ๊ฐ์ด ๋ณธ๋ค.
// We want a <p> element, with some text content and two classes attached. // Returns <p class="very-special-text super-big">Such unique text</p> createElement('p', { content: 'Such unique text', classNames: ['very-special-text', 'super-big'] }); // To make this method even more useful, it should always return a default // element when any argument is left out or none are passed at all. createElement(); // <div class="module-text default">Very default</div>
์ด ๊ตฌํ์ ๋ง์ด ํ์ง ์์ง๋ง, ๊ธฐ๋ณธ์ ์ ๋ฒ์์์ ์๋นํ ์ปค์ง ์ ์๋ค.
// Without default parameters it looks quite bloated and unnecessary large. function createElement (tag, config) { tag = tag || 'div'; config = config || {}; const element = document.createElement(tag); const content = config.content || 'Very default'; const text = document.createTextNode(content); let classNames = config.classNames; if (classNames === undefined) { classNames = ['module-text', 'default']; } element.classList.add(...classNames); element.appendChild(text); return element; }
์ ์ดํด๋ณด์ ๋ฌด์์ผ๊น?
๋งค๊ฐ๋ณ์ tag ์ config์ ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ๊ณ , ๊ทธ๊ฒ๋ค์ด ํต๊ณผ๋์ง ์๋ ๊ฒฝ์ฐ
์ค์ ๋ก ์ปจํ
์ธ ๋ฅผ ์ง์์ ์ผ๋ก ๋ง๋ค ์ ์๋ค.
๋ง์ฝ์ classNames๊ฐ ์ ์๋์ด์ง๊ณ , ๊ธฐ๋ณธ์ ์ธ ๋ฐฐ์ด์ด ์ง์ ๋์ง ์์๋ค๋ ๊ฒ์ ์ฒดํฌํ๋ฉด
๋ง์ง์์ผ๋ก ๋ง๋ค์ด ์ง๊ณ ์์ ํ๋ ์๋ฆฌ๋จผํธ๋ฅผ ์ฐ๋ฆฌ๊ฐ ๊ทธ๊ฒ์ ๋ฆฌํดํ๊ธฐ ์ ์
์ง๊ธ ์ด ํจ์๋ฅผ ๋ณด๋ฉด, ๊น๋ํ๊ฒ ๊ตฌํ๋์๊ณ , ์ฐ๊ธฐ๋ ๋น ๋ฅด๊ณ , ๋ชฉ์ ์ด ๋ฌด์์ธ์ง ๋ ๋ช
๋ฐฑํ๋ค.
// Default all the things function createElement (tag = 'div', { content = 'Very default', classNames = ['module-text', 'special'] } = {}) { const element = document.createElement(tag); const text = document.createTextNode(content); element.classList.add(...classNames); element.appendChild(text); return element; }
์ฐ๋ฆฌ๋ ํจ์์ ๋ก์ง์ ๋ง์ง์ง ์์์ง๋ง ํจ์์ ๋ด์ ๋ชจ๋ ๊ธฐ๋ณธ ์กฐ์ ์ ์ง์ ๋ค. ํจ์์ ์๊ทธ๋์ฒ๋ ๋ชจ๋ ๊ธฐ๋ณธ์ ํฌํจํ๋ค.
๋์๊ฒ ๋ ๋์๊ฑฐ ์ด ํํธ๋ฅผ ์ค๋ช
ํ๋๊ฒ์ ์กฐ์ฉํ ํผ๋์ค๋ฌ์ธ์ง๋ ๋ชจ๋ฅธ๋ค.
// What exactly happens here? function createElement ({ content = 'Very default', classNames = ['module-text', 'special'] } = {}) { // function body }
์ฐ๋ฆฌ๋ ๊ธฐ๋ณธ ์ค๋ธ์ ํธ ๋งค๊ฐ๋ณ์๋ฅผ ์ ์ธํ ๋ฟ ๋ง ์๋๋ผ, ๊ธฐ๋ณธ ์ค๋ธ์ ํธ ์์ฑ๋ค๋ ์ ์ธํ๋ค. ์ด๊ฒ์ ๊ทธ๊ฒ์ ๋ง๋ค์๋ค ๋ ๋ช
๋ฐฑํ ๊ธฐ๋ณธ ํ๊ฒฝ์ด ๋ณด๋ ๊ฒ๊ณผ ๊ฐ์ด ์ ๊ณตํ๋ ๊ฒ์ ๊ธฐ๋ณธ ๊ฐ์ฒด(config={})์ ๊ธฐ๋ณธ ์์ฑ์ ๋์ค์ ์ค์ ํ๋ ๊ฒ๋ณด๋ค. ๋ช๊ฐ์ง ์ถ๊ฐ์ ์ธ ์๊ฐ์ ๋ณด์๋ฉด ๊ทธ๊ฒ์ ์ฌ์ฉํ๋ค๋ฉด ํ์ง๋ง ๊ทธ๊ฒ์ ๋น์ ์ ์์
์ ํ๋ฆ์ ํฅ์ ์ํฌ๊ฒ์ด๋ค.
๋ฌผ๋ก ์ฐ๋ฆฌ๋ ๋ ํฐ ๊ตฌ์ฑ์ ์ฃผ์ฅํ ์ ์๊ณ ์ค๋ฒํด๋๋ฅผ ๋ง๋ค์ ์์ง๋ง ๊ทธ๊ฒ์ ๋จ์ง ํจ์ ๋ณธ๋ฌธ์ ๊ธฐ๋ณธ ์ ์ธ ์กฐ์ ์ ํ๋ ๊ฒ ์
๋๋ค.
๋ฉ์๋๊ฐ ๋ณ์ ๋งํผ ํฐ ๊ตฌ์ฑ ๊ฐ์ฒด์ ์์ฉ ํ๋ค๋ฉด, ์ฝ๋๋ ์๋นํ ํฌ๊ฒ ๋ ์ ์๋ค. ๊ทธ๊ฒ์ ๋ช๊ฐ์ ๋ณ์๋ค์ ์ค๋นํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ค๋ธ์ ํธ๋ฅผ ์ถ๊ฐํ๋ค. Property shorthands๋ syntactic sugar์ด๋ค. ์ด ๋จ๊ณ๋ ์งง๊ณ ๋ ์ฝ์ด์ด์ผ ํ๋ค.
const a = 'foo', b = 42, c = function () {}; // Previously we would use these constants like this. const alphabet = { a: a, b: b, c: c }; // But with the new shorthand we can actually do this now, // which is equivalent to the above. const alphabet = { a, b, c };
Okay, ๋ค๋ฅธ ๋ค์, ๋ ์ผ๋ฐ์ ์ธ ์์ ์ด๋ค. ๋ค์ ํจ์๋ ๋ช๊ฐ์ง ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ , ๊ทธ๊ฒ์ ๋ณํ์ํค๊ณ ๋ค๋ฅธ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
function updateSomething (data = {}) { const target = data.target; const veryLongProperty = data.veryLongProperty; let willChange = data.willChange; if (willChange === 'unwantedValue') { willChange = 'wayBetter'; } // Do more. useDataSomewhereElse({ target: target, property: veryLongProperty, willChange: willChange, // .. more }); }
์ข
์ข
์ฐ๋ฆฌ๋ ๋ณ์์ ์ด๋ฆ๊ณผ ๊ฐ์ฒด ์์ฑ์์ด๋ฆ์ ๊ฐ๊ฒ ํ๋ค. property shorthand๋ ์ด๊ฒ์ ์ด์ฉํ์ฌ, ํฉ์น๋ค. ์ฐ๋ฆฌ๋ ์ฐ๋ฆฌ์ ์ฝ๋์ ํฐ ๊ฒ์ ์งง๊ฒ ํ ์ ์๋ค.
function updateSomething (data = {}) { // Here we use destructuring to store the constants from the data object. const { target, veryLongProperty: property } = data; let { willChange } = data; if (willChange === 'unwantedValue') { willChange = 'wayBetter'; } // Do more. useDataSomewhereElse({ target, property, willChange }); }
๊ฒฐ๊ณผ์ ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ์ ์๋ก์ด ๊ธฐ๋ฅ์ค์ ํ๋์ด๋ค. ์ฝ๋๋ ๋น ๋ฅด๊ฒ ๋์์ฃผ๊ณ ํจ์๋ ๋ด์ฉ์ ๊น๋ํ๊ฒ ๋๋ค.
// Instead of writing the function keyword everytime, const module = { foo: 42, bar: function (value) { // do something } }; // we can just omit it and have shorter declarations const module = { foo: 42, bar (value) { // do something } };
Default parameters์ property shorthands๋ ๋น์ ์ ๋ฉ์๋๋ฅผ ๋ ์ ๊ตฌ์ฑํ๋ ์ข์ ๋ฐฉ๋ฒ์ด๊ณ , ๋ช๊ฐ์ ๊ฒฝ์ฐ๋ ์งง์ ๊ฒ์์๋. ์ ๋ฐ์ ์ผ๋ก, default function parameters๋ ์ฐ๋งํ์ง ์์ง ์๊ฒ ๋ฉ์๋๋ฅผ ๋ชฉํ์ ๋ง๋๋ก ๊ธฐ๋ณธ์ ์ผ๋ก ์ค๋นํ๋ ๊ฒ์ด๋ค. ๋ง์ฝ ์ง์ ์
์๋ง๋ shorthands๋ ์ฌ์ค ์ปฝ์น๋ ๊ธฐ๋ฅ์ ํ๋์ด์ง๋ง ๋ชจ๋ ๋ณ์๋ค์ ์ฐ๋๋ฐ ์ ์ด๋ ์์ฐ์ ์ธ๊ฒ์ ์ฐพ์ ์ ์๋ค. ๊ฐ์ฒด์ ๊ตฌ์ฑ, ๊ทธ๋ฆฌ๊ณ ํจ์์ ํค์๋ ์ด๋ค.
๋ฒ์จ default parameters ์ property shorthans๋ฅผ ์ฌ์ฉํ๋?