Michael Wanyoike, Sam Deering 두 사람이 sitepoint에 저술한 글을 번역한 내용입니다.
자바스크립트 개발자라면 꼭 읽어볼만한 유용한 축약기법들이 소개되어있으니 참고하시면 좋을 것 같습니다.
velog는 아니지만 다른 곳에 번역본을 더 깔끔하게 올려놓으신 분도 계시니
저 포스트를 참고하셔도 좋을 것 같습니다!
if .. else 조건문을 한 라인으로 줄여주는 유용한 기법입니다.
기존
const x = 20;
let answer;
if (x > 10) {
answer = "greater than 10";
} else {
answer = "less than 10";
}
축약
const answer = x > 10 ? "greater than 10" : "less than 10";
또한 중첩해서 사용도 가능합니다.
const answer = x > 10 ? "greater than 10" : x < 5 ? "less than 5" : "between 5 and 10";
기존 변수를 다른 변수에 할당하고 싶을 때, 기존 변수가 null, undefined 또는 비어있는 값이 아닌지 확인하고 싶을 수 있습니다. 이 경우에는 보통 긴 if 조건문을 사용하거나 간략계산법을 축약코딩을 사용할 수 있습니다.
기존
if (variable1 !== null || variable1 !== undefined || variable1 !== '') {
let variable2 = variable1;
}
축약
const variable2 = variable1 || 'new';
믿기지 않으신다면 es6console에 아래 코드를 복사하여 확인해보세요!
let variable1;
let variable2 = variable1 || 'bar';
console.log(variable2 === 'bar'); // prints true
variable1 = 'foo';
variable2 = variable1 || 'bar';
console.log(variable2); // prints foo
variable1에 falsy한 값을 넣을 경우 bar 문자열이 variable2에 할당될 겁니다.
함수를 시작하기 전 변수를 선언하는 것은 좋은 자세입니다. 이 축약기법은 동시에 여러개의 변수를 선언함으로써 시간과 코드라인을 줄일 수 있습니다.
기존
let x;
let y;
let z = 3;
축약
let x, y, z=3;
사소한 것일지 모르나, 알아두면 좋을 것 같습니다. if 조건문을 사용 시 때때로 대입 연산자를 생략할 수 있습니다.
기존
if (likeJavaScript === true)
축약
if (likeJavaScript)
위 두가지 예제가 정확하게 일치하지는 않습니다. 그 이유는 기존방법의 경우 true일 경우에만 조건문을 실행하는 반면 축약기법에서는 truthy 일 경우 통과하도록 되어있기 때문입니다.
다음 예제를 보시면 a가 true가 아닐 경우, 조건문을 실행합니다.
기존
let a;
if ( a !== true ) {
// do something...
}
축약
let a;
if ( !a ) {
// do something...
}
만약 외부 라이브러리에 의존하지 않고 바닐라 자바스크립트만을 사용하길 원한다면 이 팁은 아주 유용합니다.
기존
const fruits = ['mango', 'peach', 'banana'];
for (let i = 0; i < fruits.length; i++)
축약
for (let fruit of fruits)
단순히 인덱스에만 접근하길 원한다면 다음과 같은 방법도 있습니다.
for (let index in fruits)
또한 리터럴 객체의 키에 접근하려는 경우에도 마찬가지로 동작합니다.
const obj = {continent: 'Africa', country: 'Kenya', city: 'Nairobi'}
for (let key in obj)
console.log(key) // output: continent, country, city
Array.forEach를 통한 축약기법
function logArrayElements(element, index, array) {
console.log("a[" + index + "] = " + element);
}
[2, 5, 9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[2] = 9
기본 값을 할당하기 위해 파라미터가 null 또는 undefined인지 확인하느라 6줄의 코드를 작성하는 것보다 Short-circuit Evaluation 계산법을 이용해 한 줄의 코드로 작성하는 방법이 있습니다.
기존
let dbHost;
if (process.env.DB_HOST) {
dbHost = process.env.DB_HOST;
} else {
dbHost = 'localhost';
}
축약
const dbHost = process.env.DB_HOST || 'localhost';
process.env.DB_HOST 값이 있을 경우 이 값을 dbHost에 할당하지만 없다면 localhost를 할당합니다. 이에 대한 정보는 여기 에서 더 살펴볼 수 있습니다.
0이 많이 포함된 숫자를 적을 때, 이 수많은 0들을 제외하고 숫자를 작성한다면 있어보이지 않을까요? 예를들어 1e7은 10,000,000 과 동일하며 1뒤에 7개의 0이 딸려온 것을 의미합니다.
기존
for (let i = 0; i < 10000; i++) {}
축약
for (let i = 0; i < 1e7; i++) {}
// All the below will evaluate to true
1e0 === 1;
1e1 === 10;
1e2 === 100;
1e3 === 1000;
1e4 === 10000;
1e5 === 100000;
자바스크립트에서 객체 리터럴 표기법은 코딩을 더 쉽게 만듭니다. ES6 는 객체에 프로퍼티를 할당하는것을 더 쉽게 만들어 주었습니다. 만약 객체의 프로퍼티 이름이 키 이름과 같을 경우에 축약기법을 사용할 수 있습니다.
기존
const x = 1920, y = 1080;
const obj = { x:x, y:y };
축약
const obj = { x, y };
기존의 함수는 읽고 쓰기가 쉽도록 되어있지만 다른 함수 호출에 중첩하여 사용하게 될 경우 다소 길어지고 헷갈리게 됩니다.
기존
function sayHello(name) {
console.log('Hello', name);
}
setTimeout(function() {
console.log('Loaded')
}, 2000);
list.forEach(function(item) {
console.log(item);
});
축약
sayHello = name => console.log('Hello', name);
setTimeout(() => console.log('Loaded'), 2000);
list.forEach(item => console.log(item));
화살표 함수와 일반 함수의 차이점은 그 생김새로도 확인할 수 있지만 this가 기존 함와 다르게 작동합니다. 따라서 위 두 예제는 완전히 동일한 예제는 아닙니다.
이 차이점에 대해 알고 싶으시다면 여기 를 클릭해주세요.
return 은 함수 결과를 반환하는데 사용되는 키워드입니다. 한 줄로만 작성된 화살표 함수에서는 return 명령어가 없어도 자동으로 반환하도록 되어있습니다. 다만 중괄호를 생략해야지만 return 키워드도 생략할 수 있습니다.
여러 라인의 코드(객체 리터럴) 를 반환하려면 중괄호 대신 () 를 사용해서 함수를 감싸면 됩니다. 다음과 같이 한 줄로 코드가 작성되었음을 확인할 수 있습니다.
기존
function calcCircumference(diameter) {
return Math.PI * diameter
}
축약
calcCircumference = diameter => (
Math.PI * diameter;
)
기존에는 if 문을 통해 함수의 파라미터에 기본 값을 지정해주었지만 ES6 에서는 함수 선언문 자체에 파라미터의 기본 값을 설정해 줄 수 있습니다.
기존
function volume(l, w, h) {
if (w === undefined)
w = 3;
if (h === undefined)
h = 4;
return l * w * h;
}
축약
volume = (l, w = 3, h = 4 ) => (l * w * h);
volume(2) //output: 24
문자열로 ' + '를 입력하며 자바스크립트 값을 추가하는 손가락 노동에 지치지 않으시나요? 더 쉬운 방법은 없을까요? 만약 ES6 사용하실 줄 안다면 백틱(backtick)을 사용해서 스트링을 감싸고 변수를 ${}로 감싸서 손쉽게 연결 할 수 있습니다.
기존
const welcome = 'You have logged in as ' + first + ' ' + last + '.'
const db = 'http://' + host + ':' + port + '/' + database;
축약
const welcome = `You have logged in as ${first} ${last}`;
const db = `http://${host}:${port}/${database}`;
유명한 프레임워크로 개발을 하고 있다면 컴포넌트나 API간 데이터를 전송하기 위해서 객체 리터럴이나 배열로 이뤄진 데이터를 사용하게 될 가능성이 큽니다. 데이터 객체가 컴포넌트에 들어가게 되면, unpack이 필요합니다.
기존
const observable = require('mobx/observable');
const action = require('mobx/action');
const runInAction = require('mobx/runInAction');
const store = this.props.store;
const form = this.props.form;
const loading = this.props.loading;
const errors = this.props.errors;
const entity = this.props.entity;
축약
import { observable, action, runInAction } from 'mobx';
const { store, form, loading, errors, entity } = this.props;
추가적으로 커스텀 변수명을 지정할 수 있습니다.
const { store, form, loading, errors, entity:contact } = this.props;
위의 코드는 구조분해할당을 통해 entity를 가져오고 난 후 contact라는 변수명을 지정한 겁니다.
한 줄 이상의 문자열을 입력하게 될 경우가 있다면 기존의 방법보다 훨씬 편한 방법이 있습니다.
기존
const lorem = 'Lorem ipsum dolor sit amet, consectetur\n\t'
+ 'adipisicing elit, sed do eiusmod tempor incididunt\n\t'
+ 'ut labore et dolore magna aliqua. Ut enim ad minim\n\t'
+ 'veniam, quis nostrud exercitation ullamco laboris\n\t'
+ 'nisi ut aliquip ex ea commodo consequat. Duis aute\n\t'
+ 'irure dolor in reprehenderit in voluptate velit esse.\n\t'
아래와 같은 방법으로 백틱(backtick)을 사용하는 방법도 있습니다.
축약
const lorem = `Lorem ipsum dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse.`
ES6 에서 소개된 스프레드 연산자는 자바스크립트 코드를 더 효율적이고 재미있게 사용할 수 있는 방법들을 제시합니다. 간단히는 배열의 값을 변환하는데 사용할 수 있습니다. 스프레드 연산자를 사용하는 방법은 점 세개(...)를 붙이면 됩니다.
기존
// joining arrays
const odd = [1, 3, 5];
const nums = [2 ,4 , 6].concat(odd);
// cloning arrays
const arr = [1, 2, 3, 4];
const arr2 = arr.slice()
축약
// joining arrays
const odd = [1, 3, 5 ];
const nums = [2 ,4 , 6, ...odd];
console.log(nums); // [ 2, 4, 6, 1, 3, 5 ]
// cloning arrays
const arr = [1, 2, 3, 4];
const arr2 = [...arr];
concat() 함수와는 다르게 스프레드 연산자는 배열 내부의 원하는 위치 어디에나 추가할 수 있습니다.
const odd = [1, 3, 5 ];
const nums = [2, ...odd, 4 , 6];
스프레드 연산자는 또한 ES6 의 구조화 대입법(destructuring notation)와 함게 사용할 수도 있습니다.
const { a, b, ...z } = { a: 1, b: 2, c: 3, d: 4 };
console.log(a) // 1
console.log(b) // 2
console.log(z) // { c: 3, d: 4 }
기본적으로 자바스크립트 함수의 파라미터값을 받지 않았을 경우, undifined로 지정합니다. 몇몇 다른 언어들은 에러 메시지를 나타내기도 합니다. 이런 기본 파라미터는 강제로 할당하는 방법은 if문을 사용해서 undefined일 경우 에러가 나도록 하거나,
Mandatory Parameter를 사용하는 방법이 있습니다.
기존
function foo(bar) {
if(bar === undefined) {
throw new Error('Missing parameter!');
}
return bar;
}
축약
mandatory = () => {
throw new Error('Missing parameter!');
}
foo = (bar = mandatory()) => {
return bar;
}
자바스크립트로 특정 값을 찾기 위한 함수를 작서앟다보면 보통 for 루프를 이용해서 접근을 하곤 합니다. 그러나 ES6 에서 find()라는 새로운 함수가 생겼습니다.
기존
const pets = [
{ type: 'Dog', name: 'Max'},
{ type: 'Cat', name: 'Karl'},
{ type: 'Dog', name: 'Tommy'},
]
function findDog(name) {
for(let i = 0; i<pets.length; ++i) {
if(pets[i].type === 'Dog' && pets[i].name === name) {
return pets[i];
}
}
}
축약
pet = pets.find(pet => pet.type ==='Dog' && pet.name === 'Tommy');
console.log(pet); // { type: 'Dog', name: 'Tommy' }
Foo.bar를 Foo['bar'] 로 적을 수 있다는 걸 알고 있으신가요? 왜 후자와 같이 코딩을 해야 하는지 의문이 들 수도 있지만, 재사용이 용이한 코드 블락을 작성하기 위해서는 매우 효율적인 방법입니다.
아래의 간단한 validation 함수를 확인해보세요
기존
function validate(values) {
if(!values.first)
return false;
if(!values.last)
return false;
return true;
}
console.log(validate({first:'Bruce',last:'Wayne'})); // true
위 함수로 validation 기능을 완벽하게 사용할 수 있습니다. 하지만 form 요소들과 validation 옵션으로 사용해야하는 영역과 규칙이 많을 경우 위 함수는 점점 복잡해지고 길어지게 됩니다. 이를 방지하기 위해서 실행시 옵션을 부과할 수 있는 포괄적인 validation함수를 작성하는 방법을 알아보겠습니다.
축약
// object validation rules
const schema = {
first: {
required:true
},
last: {
required:true
}
}
// universal validation function
const validate = (schema, values) => {
for(field in schema) {
if(schema[field].required) {
if(!values[field]) {
return false;
}
}
}
return true;
}
console.log(validate(schema, {first:'Bruce'})); // false
console.log(validate(schema, {first:'Bruce',last:'Wayne'})); // true
위의 예시처럼 사용한다면 모든 form에 공통으로 적용할 수 있는 validation 함수를 작용할 수 있습니다.
비트 연산자는 자바스크립트를 처음 배울 때를 제외하고는 한 번도 적용해 본 적 없는 연산자일 겁니다. 애당초 이진법으로 코딩하지 않는다면 1과 0을 사용 할 일이 없죠.
하지만 단항 비트 논리부정 연산자를 효율적으로 사용할 수 있는 방법을 알려드립니다.
바로 Math.floor() 함수의 대체용으로 사용할 수 있다는 것이죠. 또 Math.floor()함수보다 훨씬 빠르게 작동한다는 장점도 있습니다. 단항 비트 논리부정 연산자에 대해서는 여기 에서 더 알아보실 수 있습니다.
기존
Math.floor(4.9) === 4 //true
축약
~~4.9 === 4 //true
Math.pow를 통해 거듭제곱을 나타낼 수 있습니다.
기존
Math.pow(2,3); // 8
Math.pow(2,2); // 4
Math.pow(4,3); // 64
축약
2**3 // 8
2**4 // 4
4**3 // 64
때때로 필요한 데이터는 숫자 형식이어야 하는데 문자열 타입이 오는 경우가 있을 수 있습니다. 하지만 이러한 타입변환은 손쉽게 해결할 수 있습니다.
기존
const num1 = parseInt("100");
const num2 = parseFloat("100.01");
축약
const num1 = +"100"; // converts to int data type
const num2 = +"100.01"; // converts to float data type
개인적으로 정말 유용한 단축기법들이기에 이렇게 소개해드립니다.
저 스스로도 다른 사람들의 코드를 볼 때 단축기법에 대해 잘 몰라 헤매는 경우가 있었는데 많은 공부가 되었습니다.
본문
번역
저도 비슷한 공부를 한 적이 있어서 몇 가지 말씀드리고 싶은 것들이 있네요!
2번 간략계산법으로 썼던 곳에서 만약 null과 undefined만 처리하고 싶으시다면 || 대신 ??를 쓸 수 있습니다
(nullish coalescing operator)
~~(Double tilde)연산자는 음수의 경우 Math.floor와 다른 결과를 출력합니다.
~~(-5.5) => -5, Math.floor(-5.5) => -6
Math.trunc 와 같습니다.
엄밀하게 따지면, parseInt()와 + 는 다른 결과가 나옵니다.
var a = '12px'
parseInt(a) // 12
+a // NaN