あなたが知らないJavaScriptの便利すぎるショートハンド19選

2017/07/14

Sam Deering

413

Articles in this issue reproduced from SitePoint
Copyright © 2017, All rights reserved. SitePoint Pty Ltd. www.sitepoint.com. Translation copyright © 2017, KADOKAWA ASCII Research Laboratories, Inc. Japanese syndication rights arranged with SitePoint Pty Ltd, Collingwood, Victoria,Australia through Tuttle-Mori Agency, Inc., Tokyo

日頃書いているJavaScriptをもっと短く書く方法を知っていますか? 目からうろこ、すぐに使えるJavaScriptのショードハンドを紹介します。

JavaScriptを使うすべての開発者に向けて、私が長年かけて身につけたJavaScriptのショートハンド(短縮記法)を資料にしました。コードの違いが分かるように通常の記述方法も併記しました。

1.三項演算子

if-else文を1行に収めた短縮記法です。

通常
const x = 20;
let answer;
if (x > 10) {
    answer = 'is greater';
} else {
    answer = 'is lesser';
}
ショートハンド
const answer = x > 10 ? 'is greater' : 'is lesser';

従来のif文を1行に収めることも可能です。

const big = x > 10 ? " greater 10" : x 

2.短絡演算に使えるショートハンド

変数の値をほかの変数に代入するには、元の変数の中身がnull、未定義、空でないことを確認します。複数の条件式を含んだ長いif文を書くか、短絡演算子(||&&)で調べます。

通常
if (variable1 !== null || variable1 !== undefined || variable1 !== '') {
     let variable2 = variable1;
}
ショートハンド
const variable2 = variable1  || 'new';

信じられませんか? 試してみてください。ES6 Consoleに下記のコードを貼り付けてください。

let variable1;
let variable2 = variable1  || '';
console.log(variable2 === ''); // prints true

variable1 = 'foo';
variable2 = variable1  || '';
console.log(variable2); // prints foo

3.変数宣言のショートハンド

関数の最初に変数の宣言・代入をするのは良い心がけです。以下のショートハンドなら、複数の変数を同時に宣言する際にかなりの時間と記述量を節約できます。

通常
let x;
let y;
let z = 3;
ショートハンド
let x, y, z=3;

4.値の存在確認に使えるショートハンド

ささいな事かもしれませんが、掲載します。if文による値の存在確認のコードを書くとき、代入演算子を省略できる場合があります。

通常
if (likeJavaScript === true)
ショートハンド
if (likeJavaScript)

注:2つの例は厳密には同じではありません。ショートハンドはlikeJavaScriptがtruthy(真だと推定できる)な値(たとえBoolean値でなくても、nullや未定義や空ではないため真として扱える値)だったときにtrueとなる仕組みです。

別の例です。変数aがtrueでない場合、ブロックのコードが実行されます。

通常
let a;
if ( a !== true ) {
// do something...
}
ショートハンド
let a;
if ( !a ) {
// do something...
}

5.JavaScriptのループ文のショートハンド

jQueryやlodashなどの外部ライブラリーに頼らず、素のJavaScriptを使う際に便利です。

通常
for (let i = 0; i < allImgs.length; i++)
ショートハンド
for (let index in allImgs)
Array.forEach文のショートハンド
function logArrayElements(element, index, array) {
  console.log("a[" + index + "] = " + element);
}
[2, 5, 9].forEach(logArrayElements);
// logs:
// a[0] = 2
// a[1] = 5
// a[2] = 9

6.短絡評価

パラメーターがnullや未定義の場合に初期値を代入するコードを6行にわたり書かなくても、短絡評価用に論理演算子を使えば1行で書けます。

通常
let dbHost;
if (process.env.DB_HOST) {
  dbHost = process.env.DB_HOST;
} else {
  dbHost = 'localhost';
}
ショートハンド
const dbHost = process.env.DB_HOST || 'localhost';

7. 10の累乗を指数で指定

割と知られた方法ですが、ゼロの数を数えることなく、大きな数を簡潔に記述できる粋な方法です。たとえば1e7は、1のあとにゼロが7個付いた数字です。10を累乗根とする指数を意味し、10,000,000を表しています(JavaScriptではfloat型に解釈されます)。

通常
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;

8.オブジェクトプロパティのショートハンド

JavaScriptでもオブジェクトリテラルを定義するのが賢明です。ES6ではオブジェクトのプロパティ値の設定が簡潔に書けます。プロパティ名がキーと一致しているときに使えます。

通常
const obj = { x:x, y:y };
ショートハンド
const obj = { x, y };

9.アロー関数のショートハンド

古典的な関数は、単体なら読みやすく書きやすいのですが、別の関数から呼び出して入れ子になると、冗長で複雑になりがちです。

通常
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));

10.暗黙の戻り値のショートハンド

関数の演算結果を受け取るためのreturn文は、1文のアロー関数で演算結果を暗黙的に受け取れます。return文を省く場合は関数の括弧(ブレース、{}記号)外します。

オブジェクトリテラルのように複数行の文を返す場合は、{}の代わりに()で関数を括うと、ひとまとまりの文として認識されます。

通常
function calcCircumference(diameter) {
  return Math.PI * diameter
}
ショートハンド
calcCircumference = diameter => (
  Math.PI * diameter;
)

11.パラメーター初期値

関数のパラメーターの初期値を定義するには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

12.テンプレート文字列

複数の変数を文字列として' + 'で連結するのに飽きた方へ。ES6が使えるならば、バッククォート(`記号)と${}記号で変数を囲むだけです。

通常
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}`;

13.分割代入のショートハンド

人気のWebフレームワークで作業しているのなら、コンポーネントやAPIにデータを受け渡すために、オブジェクトリテラルで配列や値を扱っていませんか。データを入れたオブジェクトがコンポーネントに届いたら、取り出して代入しますよね。

通常
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;

14.複数行にわたる文字列のショートハンド

複数行にわたる文字列を書くとき、以下の書き方をしませんか。

通常
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'

もっと楽な方法があります。バッククォート(`記号)を使います。

ショートハンド
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.`

15.スプレッド演算子のショートハンド

ES6から導入されたスプレッド演算子には、JavaScriptを効率的で楽しくする使い道があります。配列関数の置き換えです。スプレッド演算子は、3点のドット記号で表します。

通常
// 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の分割代入の文に使えます。

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 }

16.必須パラメーターのショートハンド

初期状態のJavaScriptは関数パラメーターに値を渡さなければundefined(未定義)になります。他言語ではエラーや警告を発します。パラメーター値の代入を徹底するためにif文でundefinedの場合にエラーを投げますが、紹介する必須パラメーターのショートハンドも使えます。

通常
function foo(bar) {
  if(bar === undefined) {
    throw new Error('Missing parameter!');
  }
  return bar;
}
ショートハンド
mandatory = () => {
  throw new Error('Missing parameter!');
}

foo = (bar = mandatory()) => {
  return bar;
}

17.Array.findのショートハンド

素のJavaScriptでfind関数を書くとき、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' }

18. Object [キー]構文を利用したショートハンド

Foo.barを、Foo['bar']と書くこともできます。ただし、書く理由は見当たりません。紹介する記法で再利用可能なコードブロックが書けます。

以下の入力値確認(バリデーション)の関数を題材にしましょう。

function validate(values) {
  if(!values.first)
    return false;
  if(!values.last)
    return false;
  return true;
}

console.log(validate({first:'Bruce',last:'Wayne'})); // true

これでも問題はありません。しかし、フォームが複数あり、それぞれ別のフィールド、別のルールで値を検証するなら、汎用的で、実行時に設定を変更するだけの検証のための関数が欲しいところです。

ショートハンド
// 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

複数のフォームに値を検証するための関数を作ることなく、すべてのフォームに再利用できる関数ができました。

19.ビット否定演算子を2度使うショートハンド

ビット演算子を初心者向けJavaScriptチュートリアルで学んでも、使う機会はありませんでした。2進数を使う必要がないのに「1と0」で作業する人はいません。

しかし、ビット否定演算子を2つ重ねると、Math.floor()(少数以下切り捨て)の代わりに使えます。しかも高速です。ビット演算子の詳細はこちらを見てください。

通常
Math.floor(4.9) === 4  //true
ショートハンド
~~4.9 === 4  //true

2017年6月14日:ES6に基づく新しいショートハンドを加筆しました。

(原文:19+ JavaScript Shorthand Coding Techniques

[翻訳:西尾 健史/編集:Livit

Michael Wanyoike

簡潔で読みやすいモジュール方式のコードを書きます。好きなことはワークフローの効率や生産性の向上に役立つ新たなテクノロジーを学ぶこと。最近はReactとJavaScriptにのめり込んでいます。

Copyright © 2017, Sam Deering All Rights Reserved.

Sam Deering

Sam Deering

JavaScriptとjQueryを専門とするフロントエンドのWeb開発者です。知識を教育のために共有すること情熱を持っています。

Loading...