sitateru tech blog: ECMAScript

sitateru tech blog

シタテルの技術やエンジニアの取り組みを紹介するテックブログです。

ラベル ECMAScript の投稿を表示しています。 すべての投稿を表示
ラベル ECMAScript の投稿を表示しています。 すべての投稿を表示

2019年3月12日火曜日

初めて見るとぎょっとするかもしれない JavaScript の構文 4 選

3月 12, 2019
こんにちは! エンジニアの諏訪です。シタテルでは主にフロントエンドを担当しています。
今日はフロントエンド制御のエンジンともいえる JavaScript に関する話題です。
1990 年代半ば Web 時代の幕開け (※) とともに誕生した JavaScript ── ほんとうの名前は ECMAScript というのだそうですが ── 今も昔も変わらずクライアント側での処理機構としては唯一無二の立ち位置を保ち続けてきました。
よく考えてみるとこれってとてもすごいことですよね!
※ 余談ですが World Wide Web の誕生から今日 (2019.03.12) でちょうど 30 年だそうです。
さて、上で「今も昔も変わらず」と書きましたが JavaScript 自身はもちろん何度も進化を重ねてきています。
その中でも ES2015 (ES6) では多くの新しい構文が追加され、処理内容によっては従来よりも大幅にシンプルな書き方ができるようになりました。
新しい構文は便利なのですが、勉強を始めたての新人やレガシーなプログラマが初めて見るとびっくりするような記法も。
今日はそんなユニークな (ちょっとぎょっとする) 記法を4つピックアップしてみました。

ドット3つ ...

JavaScript のコードで、3つ並んだドットを見たことがありませんか。
let array = [ 1, 2, 3 ]

let result = [ 0, ...array ]
こんなコードを初めて見た時は「・・・あれ〜?」と脳が一瞬フリーズしてしまうこと必至です。ちなみにだじゃれです。
こちらは スプレッド構文 (spread syntax) と呼ばれるもので、 ES2015 で導入された新しい記法です。
配列やオブジェクトの展開操作を楽にしてくれます。
展開操作って?
大雑把に言うと Array や Object の外側の括弧を取り払って丸裸にします
例えばこういうことです。さっきの Array の例だと:
let array = [ 1, 2, 3 ]

let result = [ 0, ...array ]
console.log(result)
// => [0, 1, 2, 3]
Object の場合だと:
let obj1 = { potato: 2, carrot: 3, onion: 5, niku: 8 }

let obj2 = { water: 65535, spice: Infinity }

let result = { ...obj1, ...obj2 }
console.log(result)
// => { "potato": 2, "carrot": 3, "onion": 5, "niku": 8, "water": 65535, "spice": Infinity }
といった具合です。
応用編として、メソッドの引数に使うことだって可能です:
function createUser(firstName, lastName, bornYear, bornMonth, bornDay) {
    // doSomeProcess
}

let name = ['Colonel', 'Sanders']
let birthday = [1890, 9, 9]
let user = createUser(...name, ...birthday) // => createUser('Colonel', 'Sanders', 1890, 9, 9) を実行するのと同じ

ビックリマーク2つ !!

ビックリマークひとつならおなじみの否定演算子ですが
ビックリマークふたつの記法もあるのか!!とびっくりびっくりしたことがあります。
じつはこれ別に ES2015 の構文ではなく、単に古典的な否定演算子を2つ重ねただけのものです。(本稿のほかの項目と違って JavaScript の黎明期からあるものです。)
Boolean (真偽値) 以外の値を Boolean にキャストしたいときに使うと便利です。
たとえば次のようなコード
function hasName (user) {
  return ( user.name !== undefined && user.name !== null && user.name !== '' )
}
は次のように書けます:
function hasName (user) {
  return !!user.name
}
条件判断をシンプルに書きたいという方、ぜひこの書き方を取り入れてみてください。

(おまけ) いろんな値の truthy / falsy について

ちょっと復習しておきたかったのでまとめてみました。
  • truthy (Boolean にキャストすると true となる) の例
    • true
    • 0 以外の Number (ex: 1, -1, 3.14, -273.15, 6.02e+23, etc)
    • Infinity と -Infinity
    • 空でない文字列 (例: "a", "false")
    • [] (空の Array)
    • {} (空の Object)
    • 1 == true (緩やかな比較)
  • falsy (Boolean にキャストすると false となる) の例
    • false
    • 0 (Number)
    • "" (空の String)
    • null
    • undefined
    • NaN
    • 1 === true (厳密な比較)
注目すべきポイント (落とし穴) は
  • 空文字列は falsy だが、空の配列や空のオブジェクトは truthy
  • “false” や 配列 [false] などは truthy
あたりでしょうか。すぐ忘れそう…

関数のアロー記法 () => {}

先ほど array の話をしたので今度は arrow の話をしなければという義務感を抱いています (嘘です)。
JavaScript といえば無名関数 (ラムダ式) ですが、ES2016 以前は無名関数を記述するには function という予約語を使うのが常でした。
setTimeout(function() {
    console.log('Hello!')
})
ES2015 からはアロー構文 () => {} を使って書くこともできるようになりました。
setTimeout(() => {
    console.log('Hello!')
})
function と () => {} どちらを使ってもよいのですが、1つだけ挙動の異なる点があるので注意が必要です。
何が異なるのかというと、メソッド内での this の扱いです; function () {} の場合はメソッドの呼び出し元のオブジェクトを指しますが、 () => {} の場合はメソッドが記述された文脈上のオブジェクトを指します。つまり、 function () {} の場合は this が動的に変わるのに対して () => {} の場合は this が固定されます。
ローカル変数レベルで後者のような挙動をするラムダ関数を closure というのでしたっけ...λ

テンプレートリテラル `${}`

プログラムを書いていて、動的に文字列を生成しないといけない場面でよくお世話になるのが printf のようなメソッド。メソッド名は言語によって様々ですが、世の中の大半の言語で提供されている構文です。
ところが JavaScript にはこれまで対応するものがなかったのです。そんな中 ES2015 になってようやく登場したのが「テンプレートリテラル」。
なんと文字列全体をバックチック ` で囲います。 (バックチックを約物に用いる言語ってあまりなかった気が…)
そしてプレースホルダは ${} と書きます。
let username = `山田太郎`
let message = `ようこそ、${username}さん!`
console.log(message) // => "ようこそ、山田太郎さん!"
そしてすごいのが、Ruby のヒアドキュメントよろしく改行をそのまま書くことができます
let body = `${client.name}様

いつも大変お世話になっております。
${company.name}の${staff.name}です。

${message.content}`
console.log(body) // => "山田太郎様\n\nいつも大変お世話になっております。\n〇〇株式会社の...
一点だけ残念なのが、ソース全体をインデントしてしまうと、そのインデント分の空白文字も無視されずに含められてしまうこと。そのためテンプレートリテラルで記載した部分はインデントすることができず、ソースの可読性が若干下がります。
Ruby のヒアドキュメントが上手にインデントを除去してくれるのに比べると少し物足りなく感じます。

以上 ES2015 のユニークな構文を一部ご紹介しました。
新しい記法は少し古いブラウザではほとんどサポートされていないものもあって、動かなかったらどうしよう…という不安から新しい書き方で書くことを躊躇してしまいがちですが、その不安を取り払ってくれる polyfill もちゃんとあります。
正しく使えば、より書きやすく読みやすく無理のない安全なコードに近づける新しい構文。しっかりと学び、追いつき、使いこなせるようになりたいものです。