IT/언어

[JavaScript] JavaScript 쇼트 코딩 테크닉(1)

개발자 두더지 2020. 11. 19. 22:43
728x90

본격적인 포스팅에 앞서 여기서 소개한 테크닉 몇 개는 실제로 추천되지 않는 표기법이라는 사실을 알립니다. 따라서 상황에 맞게 사용하시길 바랍니다.

 

기본


개행과 스페이스를 없앤다.

Before

var a = 1,
    b = 2;
console.log( a, b );

After

var a=1,b=2;console.log(a,b);

변수 선언(var)을 생략하고, 변수의 값이 동일한 경우 모아서 작성한다.

Before

var a = 1,
    b = 1;

After

a=b=1;

값 혹은 계산의 생략


소수점의 생략

Before

console.log(1+0.5);

After

console.log(1+.5);

아래 세 자리 이상이 0인 경우 지수로 표현

Before

console.log(1000);

After

console.log(1e3);

세 자리 이상이 아닌 경우는 효과가 없다. 예를 들어 1일을 밀리 초로 변환하자면 86400000이지만, 이것을 864e5로 표기하면 세 개의 문자를 절약할 수 있다. 또한 소수점의 경우, 네 자리부터 효과가 있다.

console.log(0.0001); // 6문자
console.log(.0001);  // 5문자
console.log(1e-4);   // 4문자

소수점을 버릴 때는 비트 연산을 실시

Before

console.log(Math.floor(1.2345));

After

console.log(1.2345|0);
console.log(~~1.2345);

반올림도 비트 연산을 실시

Before

a=Math.round(10.3);
b=Math.round(10.6);
console.log(a,b);

After

a=10.3+.5|0;
b=10.6+.5|0;
console.log(a,b);

0.5를 더해 비트 연산을 하면 반올림 한 정수값을 얻을 수 있다.

지수를 지수연산자를 이용해 표현 (ES6)

Before

console.log(Math.pow(-3,2));

After

console.log(-3**2);

이중계승을 비트 시프트로 구현

Before

console.log(131072);

After

console.log(1<<17);

-1판정을 비트 연산으로 구현

예를 들어, indexOf 메소드로 조건판정을 할 때, 아래와 같이 -1과 비교하게 되지만,

Before

z='abcdefg';
if(z.indexOf('a')!==-1){
  console.log('a in z');
} else {
  console.log('a not in z');
}
// 'a in z'

비트연산자 ~로 -1만을 false로 판정할 수도 있다.

After

z='abcdefg';
if(~z.indexOf('a')){
  console.log('a in z');
} else {
  console.log('a not in z');
}
// 'a in z'

이것은 -10의 비트반전 (기호를 포함하여 1에 묻혀 있는 상태) 이므로, 조건식에서는 0이외의 숫자형(음수를 표함하여) 모두를 true로 판정하기 때문이다.
반대로 -1만을 true로 하고 싶은 경우는 !~z.indexOf('a')등을 사용한다.
-1을 리턴하는 메소드로써 indexOf외에 lastIndexOf, search, findIndex등이 존재한다.

제로 패딩

행이 맞지 않는 숫자의 제로 패딩 (행이 맞추기 위해 0을 삽입) 하는 경우에,
원하는 행의 수부터 1을 뺀 수의 '0'문자열 (예를 들어, 3행을 얻고 싶은 경우 00) 을 숫자의 앞에 더하고,
slice()를 사용하여 끝에 부터 트리밍하는 방법이 사용된다.

a = 1;
a = ('00'+a).slice(-3);
console.log(a);

그러나, 2행을 얻을 경우만 3항 연산자가 제일 코드가 짧다.

// 2행의 제로패딩

a=1;

// if문의 경우, 15문자
if(a<10)a='0'+a;

// 3항 연산자의 경우, 14문자 
a=a<10?'0'+a:a;

// slice의 경우,19문자
a=('0'+a).slice(-2);
a = 1;

// 3항 연산자의 경우, 27문자
a=a<10?'00'+a:a<100?'0'+a:a;

// slice의 경우, 20문자
a=('00'+a).slice(-3);

사실 ES2017에서는 패딩용 메소드 padStart()가 존재하지만, 쇼트 코드 시점에서 말하자면 6행 이상이 아니라면 효과가 없다.

// 6행의 제로 패딩
a=1;

// slice의 경우, 23문자
a=('00000'+a).slice(-6);

// padStart의 경우, 22문자
a=(''+a).padStart(6,0);

또한, 년원일, 시분초 등의 숫자가 섞여있는 문자열에 대한 제로패딩은 replace()로 하는 방법이 존재한다.

a='2017/4/5';
a=a.replace(/(\D)(\d)(?=\D|$)/g,"$10$2");
console.log(a)

위치변환 처리의 부분에 대해 3행 이상의 경우는 후방 참조가 아닌 함수로 처리하는 쪽이 더욱 코드가 짧다.

true/false를 !0/!1 로 대입

Before

console.log(true,false);

After

console.log(!0,!1);

배열과 같이 문자열로부터 1개의 문자를 추출하는 방법

Before

console.log('아이우에오'.charAt(2));

After

console.log('아이우에오'[2]);

문자열을 배열화하는 경우, 구분 문자로 숫자를 사용

Before

var a='abc,def,ghi,jkl,mno';
console.log(a.split(','));

After

var a='abc0def0ghi0jkl0mno';
console.log(a.split(0));

이 방법으로 배열의 짧은 코드화에도 사용할 수 있다.

Before

a=['aa','bb','cc','dd','ee'];
console.log(a)

After

a='aa0bb0cc0dd0ee'.split(0);
console.log(a)

5개 이상의 문자열 배열의 경우, 1개의 문자열을 split으로 나눈는 쪽이 문자수를 감소할 수 있다.
또한, 문자열의 1개의 문자씩 배열에 저장하고 싶은 경우,

Before

a='abcdefg'.split('');
console.log(a);

After

a=[...'abcdefg'];
console.log(a);

같은 문자가 반복되는 문자열을 만들 때, repeat()을 사용 (ES6)

Before

console.log('aaaaaaaaaaaaaa');

After

console.log('a'.repeat(13));

n회 반복한 문자열을 얻고 싶은 경우, repeat()을 사용한다.
13문자 이상이 아니라면 쇼트 코드로써의 효과가 없다.
그러나 repeat()은 현대 Firefox에서만 대응되므로,

After

console.log(Array(17).join`a`);

n+1의 배열을 만들기를 반복해 리턴시키고 싶은 경우 join하는 방법을 사용한다.
이 방법은 16문자 이상이 아니라면 쇼트 코드로써의 효과가 없다.
또한, 배열 그대로가 좋은 경우 fill() 메소드를 사용할 수 있다. (ES6)

After

console.log(Array(17).fill('a'));

배열생성에 Date를 사용

Before

console.log(Math.random()*2&1);

After

console.log(new Date&1);

미리초를 리턴하는 Date는 난수 생성 메소드 대신에 사용할 수 있다.

*배열의 값을 얻어내는 데에 분할 대입을 사용(ES6) *

Before

a=0;
b=0;
c=[1,[2,3,4],5];
a=c[0];
b=c[1][0];
console.log(a,b);

After

a=0;
b=0;
c=[1,[2,3,4],5];
[a]=c;
[,[b]]=c;
console.log(a,b);

배열의 0번째에 접근하는데에 분할 대입을 이용하면 (1개의 문자정도이지만) 쇼트 코드화할 수 있다.
이 방법을 문자열에도 적용할 수 있다.

After

a='';
b='xyz';
[a]=b;
console.log(a);
// -> 'x'

배열의 복사에 스플릿구문을 사용(ES6)

Before

a=[1, 2, 3];
b=a.slice(); // 11문자
b.push(4);
console.log(a, b);

After

a=[1, 2, 3];
[...b]=a; // 8문자
b.push(4);
console.log(a, b);

스플릿 연산자를 사용하면 slice()를 사용했을 때보다 짧은 코드로 배열을 복사할 수 있다.

배열이나 객체의 연결에 스플릿 구문을 사용(ES6)

Before

a=[1,2,3],b=[4,5,6];
a.push.apply(a,b);
console.log(a);

After

a=[1,2,3],b=[4,5,6];
a.push(...b);
console.log(a);

After

a=[1,2,3],b=[4,5,6];
console.log([...a,...b]);

Result

[1, 2, 3, 4, 5, 6]

스플릿 구문을 사용하면 배열이나 객체를 분할하여 대입할 수 있다.
또한 같은 방법으로 객체의 머지도 가능하다.

Before

a={z1:1,z2:2,z3:3}
b={z2:4,z3:5,z4:6}
c=Object.assign(a,b) // 18문자
console.log(c)

After

after
a={z1:1,z2:2,z3:3}
b={z2:4,z3:5,z4:6}
c={...a,...b} // 11문자
console.log(c)

Result

{ z1: 1, z2: 4, z3: 5, z4: 6 }

배열의 제일 첫 요소를 삭제 (ES6)

Before

a=[1,2,3,4,5,6];
b=a.slice(1);
console.log(b);

After

a=[1,2,3,4,5,6];
[,...b]=a;
console.log(b);

Result

[2, 3, 4, 5, 6]

스플릿 구문을 사용하여 b를 가변의 길이로 하는 것으로 배열의 맨 앞 요소를 삭제한 배열을 리턴할 수 있다(콤마를 반복해서 리턴하여 여러 개를 삭제하는 것도 가능하다).
그러나 이 방법은 맨 뒤의 요소로부터 배열을 삭제하도록 응용하는 것을 불가능하다.

 

** 16진수 문자열의 10진수화 생략 **

Before

a='10';
console.log(parseInt('10',16));

After

a='10';
console.log('0x'+a-0);

Result

16

마지막에 숫자형 0을 계산하는 것으로 전체를 숫자형으로 변환하고 결과를 10진수화할 수 있다.
또한 2진수인 경우, 0b, 8진수인 경우 0o로 변환할 수 있다.

 

배열수의 확인에 length 메소드가 아닌 in 연산자를 사용

Before

a=[1,2,3];
console.log(a.length>3); // 10문자

After

a=[1,2,3];
console.log(3 in a); // 6문자

Result

false

Array객체의 경우 in 연산자에 의해 인덱스가 존재하는지 검사하는 것이 가능해, length 메소드를 사용하는 것보다 문자 수가 적어진다.
문자열의 경우에는 in연산자를 사용할 수 없지만 (문자열 객체의 경우 다른) , 직접 접근하는 방법으로 length를 사용하지 않고 문자 수를 확인할 수 있다.

Before

a='xyz';
console.log(a.length>3); // 10문자

After

a='xyz';
console.log(!!a[3]); // 6문자

Result

false

참고자료

qiita.com/ichimonji_haji/items/f602f6c437be9e7daa88#%E5%80%A4%E3%82%84%E8%A8%88%E7%AE%97%E3%81%AE%E7%9C%81%E7%95%A5

728x90