Upgrade to Pro — share decks privately, control downloads, hide ads and more …

はてなリモートインターンシップ2023 フロントエンドブートキャンプ講義資料

Hatena
October 18, 2023

はてなリモートインターンシップ2023 フロントエンドブートキャンプ講義資料

Hatena

October 18, 2023
Tweet

More Decks by Hatena

Other Decks in Programming

Transcript

  1. Frontend Boot Camp
    2023-08-23
    #hatenaintern)*)+

    View full-size slide

  2. このブートキャンプのゴール
    • 皆さんが主に後半のチーム開発でフロントエンドに関わるようなタスクに取り組む際
    に困らない最低限の知識をつけてもらう
    • この講義で扱う"フロントエンド"の領域は JavaScript/TypeScript/React
    • Web 開発において年々重要度を増しているフロントエンドを⾼速にキャッチアップ
    してもらう
    • 講義のボリュームが⼤きいこともあり、周辺技術に関する説明を省略する場合もあ

    インターンが終わった後も React や TypeScript など、フロントエンド技術について知る
    際の⼿助けになれば良いと思っています。
    #hatenaintern)*)+

    View full-size slide

  3. 現代のフロントエンドについて
    (/0min)
    #hatenaintern)*)+

    View full-size slide

  4. 現代のフロントエンドに
    ついて
    例えば、React*製のアプリケーションをつ
    くって公開するケースを考えてみましょう。
    レイアウトを組むことはもちろん、アプリ
    ケーションが表⽰されるまでの流れを考え
    てみると必要とされる知識も多くなってき
    ます。
    Frontend Developer Roadmap: Learn to
    become a modern frontend developer
    ! React ‒ ユーザインターフェース構築のための JavaScript ライブラリ
    #hatenaintern)*)+

    View full-size slide

  5. 様々な動作環境の⼀例
    それぞれの環境には、これらの技術によって備えることができます。
    • 古いスマホやパソコン(IE や古いバージョンのブラウザ)
    • Web 標準
    • アクセシビリティ機能を使っているユーザ
    • アクセシビリティ (accessibility, a88y)
    • (利⽤制限がかかっている)遅い‧不安定なインターネット
    • パフォーマンス対策
    それぞれ、どのように対策するのか⾒ていきます。
    #hatenaintern)*)+

    View full-size slide

  6. 例: React アプリをユーザに表
    ⽰するには?
    1. (開発者)実装
    • TypeScript の型チェック;、最新の JavaScript 構⽂での開発
    2. (開発者)ビルド
    • Web 標準
    • パフォーマンス対策
    3. (ユーザー)Web ページへのリクエスト
    • html を読み込み、それに付随するリソースを読み込むf
    4. (ユーザー)ページを表⽰
    • 読み込んだリソースを元にページを表⽰する
    • アクセシビリティ (accessibility, aAAy)
    ! 読み込むファイルが⼤きい‧多いほど、次の段階であるページ表⽰が遅くなる
    ! なぜ TypeScript を使うのか? - TypeScript Deep Dive ⽇本語版
    #hatenaintern)*)+

    View full-size slide

  7. 例: React アプリをユーザに表
    ⽰するには?
    • Web 標準
    • パフォーマンス対策
    • アクセシビリティ (accessibility,
    aAAy)
    具体的にはどうのように対策していくの
    か、開発の流れと共に⾒ていきます。
    #hatenaintern)*)+

    View full-size slide

  8. 例: React アプリをユーザに表⽰するには?
    React を JavaScript のアプリケーションと考えるならば、素朴に
    html と⼀緒にアプリのソースコードを配信してブラウザで表⽰で
    きるはずです。
    > ls
    index.html main.js






    #hatenaintern)*)+

    View full-size slide

  9. 例: React アプリをユーザに表⽰するには?
    しかし、React/TypeScript で開発していた場合はどうでしょうか?









    // main.tsx
    const App = () => {
    const user: User | null = useUser()
    return (

    Α͏ͦ͜ɺ{user?.name ?? 'ήετ'}͞Μɻ

    )
    }
    const container = document.getElementById('root')
    const root = createRoot(container!)
    root.render()
    #hatenaintern)*)+

    View full-size slide

  10. 例: React アプリをユーザに表⽰するには?
    • TypeScript をブラウザが解釈できない
    • JavaScript なら const user = useUser()
    • TypeScript なら const user: User | null = useUser()
    • JSX をブラウザが解釈できない
    • JSX とは const label = () => (...) のように、 HTML タグを書いてあるものN
    • 新しい構⽂を解釈できないような、(未アップデートの)古いブラウザが存在する
    • ESabab で追加された構⽂ ?. h や ?? jなど
    => JSX や TypeScript、新しい JavaScript 構⽂をトランスパイル@によってブラウザが解釈できるように書き換える。
    ! 未対応の構⽂をターゲットが解釈可能な構⽂へ書き換えることによって、その環境でもコードが動くようにすること。
    ! Null 合体演算⼦ (??) - JavaScript | MDN
    ! オプショナルチェーン (?.) - JavaScript | MDN
    ! JSX の導⼊ ‒ React
    #hatenaintern)*)+

    View full-size slide

  11. トランスパイル
    最新の⽂法で書いたコードを多くの古い環境(古いブラウザなど)でも
    動くように古い記法へ変換すること。
    例えば、アロー関数式とテンプレートリテラル、Null 合体演算⼦ (??)を
    使った関数があります。
    const hello = (name) => `hello, ${name ?? "ήετ"}!`
    hello("hatena")
    // > hello, hatena!
    hello()
    // > hello, ήετ!
    #hatenaintern)*)+

    View full-size slide

  12. トランスパイル
    アロー関数式とテンプレートリテラルは ES4567(ES9) から、Null 合体演
    算⼦ (??)は ES4545 から導⼊されたもので、それ以降アップデートしてい
    ないブラウザでは動きません。
    そのため、トランスパイルによって次のように変換します。
    var hello = function hello(name) {
    return "hello, " + (name !== null && name !== void 0 ? name : "ήετ") + "!"
    }
    hello("hatena")
    // > hello, hatena!
    hello()
    // > hello, ήετ!
    #hatenaintern)*)+

    View full-size slide

  13. ツールチェイン(
    • 前スライドで説明したトランスパイルを⾏うツールはトランスパイラと呼ばれ、代表的なものは 3 つあります。
    • バンドラはトランスパイルしたモジュール群をできるだけ最適にバンドルしてくれるツールです。
    • 最近はこれらのツールを結合する統合ツールのようなもの (Romec, Denog) が登場したりもしています。
    トランスパイラ
    • Babel (JavaScript)
    • SWC (Rust)
    • esbuild (Golang)
    バンドラ
    • Webpack
    • Rollup
    • Parcel (SWC)
    • Snowpack, Vite (esbuild)
    ! https://deno.land/
    ! https://rome.tools
    #hatenaintern)*)+

    View full-size slide

  14. Web 標準
    Chrome, IE, Safari, Firefox など世の中には多くのブラウザがあり、そのバージョンもユーザーによって
    異なっています。
    • Web 標準()という活動によって、すべてのブラウザで構⽂や API が同じ振る舞いをすることを⽬指して
    いる((
    • JavaScript(ECMAScript)、HTML、DOM API、CSS の対応バージョンもブラウザによって異なる
    • もし古いブラウザでの動作をサポートするなら?
    • API が⾜りない場合は polyfill を⽤いて補う
    • 新しい JavaScript トランスパイルによって古い構⽂に変換する
    !! 2021 年のウェブ標準とブラウザ | gihyo.jp
    !" Web standards (ウェブ標準) - MDN Web Docs ⽤語集: ウェブ関連⽤語の定義 | MDN
    #hatenaintern)*)+

    View full-size slide

  15. Web 標準
    ブラウザごとのサポート状況は以下のサイトで確認できます。
    • MDN%&
    • https://developer.mozilla.org/ja/docs/Web
    • ウェブ上には有象無象のあらゆる情報が転がっているので、フロントエンドやウェブ
    についてのことで困ったらまずは MDN を⾒るのがオススメ
    • Can I use
    • https://caniuse.com
    !" mozilla のドメイン下にあるが、Google やマイクロソフトなどが Open Web Docs という団体を通じて⽀援をしている https://opencollective.com/open-web-docs/updates/
    introducing-open-web-docs
    #hatenaintern)*)+

    View full-size slide

  16. アクセシビリティ (accessibility, a55y)
    アクセシビリティ | MDN
    ウェブ開発におけるアクセシビリティとは、何らかの理由により能⼒に制約がある場合でも、可能な限り多く
    の⼈々がウェブサイトを使⽤できるようにすることを意味します。アクセシビリティとは、個⼈の⾝体的‧認
    知的能⼒やウェブへのアクセス⽅法に関わらず、可能な限りアクセス可能なコンテンツを開発することです。
    W"C - Accessibility
    「ハードウェア、ソフトウェア、⾔語、⽂化、所在地、物理的/精神的能⼒にかかわらず、ウェブは基本的に
    すべての⼈に向けて設計されています。ウェブがこの⽬的を達成できると、さまざまな聴⼒、視⼒、認知能⼒
    をもつ⼈々がウェブにアクセスできるようになります。」
    #hatenaintern)*)+

    View full-size slide

  17. アクセシビリティ (accessibility, a55y)
    • セマンティックマークアップ,- (意味的 HTML)
    • リストには や を使うなど
    • これによって、スクリーンリーダー などが適切に解釈できるようになる。
    • 代替テキスト,V
    • ネットワークエラーなどで画像の読み込みに失敗した際は、alt にいれた⽂字を表⽰するなど
    • キーボード操作のサポート
    • キーボード操作 (Tab キーでのフォーカス移動など) のサポートなど
    !" HTML の画像 - ウェブ開発を学ぶ | MDN
    !" Semantics (セマンティクス) - MDN Web Docs ⽤語集: ウェブ関連⽤語の定義 | MDN
    #hatenaintern)*)+

    View full-size slide

  18. パフォーマンス対策
    (利⽤制限がかかっている)遅い‧不安定なインターネットを使っているユーザーが
    主に対象となる。
    • ユーザーの転送量や計算資源を浪費させるケース
    • 無駄な js や css、画像などのアセットのダウンロード
    • アプリケーションを 1 つにバンドルした巨⼤なファイル
    • 遅れて表⽰された要素によってページのレイアウトが変わってしまうkl
    => 最初のページに必要なものだけダウンロードして素早く表⽰するべき
    !" Cumulative Layout Shift (CLS) https://web.dev/i!=n/ja/cls/
    #hatenaintern)*)+

    View full-size slide

  19. パフォーマンス対策
    (利⽤制限がかかっている)遅い‧不安定なインターネットを使っているユーザーが主に対象とな
    る。
    • 世界中のユーザーからのリクエスト
    • 例:⽇本にあるサーバーより前段、よりユーザーに近い位置(CDN, Edge)でリクエストを処理する
    • 複数回訪れる可能性のあるアプリケーション
    • CDN やブラウザキャッシュを⽤いて、何度も同じファイルをダウンロードする必要性を抑える
    • 1 度に巨⼤なファイルのダウンロードによって、ページの表⽰速度が遅い
    • コンテンツの表⽰タイミングにあわせてリソースを取得する
    • モジュール分割 (Code Splitting)、事前‧遅延読み込み (preload, defer, lazy)
    #hatenaintern)*)+

    View full-size slide

  20. 例: React アプリをユーザに表
    ⽰するには?
    1. (開発者)実装
    • TypeScript の型チェック、最新の JavaScript 構⽂での開発
    2. (開発者)ビルド
    • 古い環境をサポートするための、Transpile, Polyfill
    • ページごとに必要最低限の Bundle, Code Splitting
    3. (ユーザー)Web ページへのリクエスト
    • html を読み込み、それに付随するリソースを読み込む
    4. (ユーザー)ページを表⽰
    • 読み込んだリソースを元にページを表⽰する
    • スクリーンリーダーやキーボード操作に対応する
    #hatenaintern)*)+

    View full-size slide

  21. JavaScript について(01min)
    #hatenaintern)*)+

    View full-size slide

  22. JavaScript について(01min)
    • ES$%&'(ES))以降に JavaScript に⼊った機能を中⼼に皆さんが
    実際にコードを読む際に知っておいて欲しい JavaScript 上の概
    念について紹介します
    • JavaScript とは · JavaScript Primer #jsprimer
    #hatenaintern)*)+

    View full-size slide

  23. きほんのき 1/2
    // ม਺ͱએݴ
    let a = "a" // let ͸্ॻ͖Մೳ
    const b = "b" // ্ॻ͖ෆՄೳ
    a = "A" // OK
    b = "B" // Cannot assign to "b" because it is a constant
    JavaScript における変数宣⾔は基本的に const を優先して使うこと
    を推奨します。変数が変更されないことがわかっている場合、コード
    を読む際の理解が容易になります。
    #hatenaintern)*)+

    View full-size slide

  24. きほんのき 1/2
    const id = "1234" // string
    const name = null // null
    const age = 2022 // number
    const isAdmin = false // boolean
    // object
    const user = {
    id,
    username: name
    age,
    isAdmin,
    memo,
    }
    user.age // 2022
    // ະఆٛϓϩύςΟͩͱ undefined ͕ฦΔ
    user.abc
    #hatenaintern)*)+

    View full-size slide

  25. きほんのき 2/2
    // ؔ਺
    function getUser(id) {
    return db.users.find(id)
    }
    const getBlog = (id) => {
    return db.blogs.find(id)
    }
    // ഑ྻ
    const array1 = [1, 2]
    // ഑ྻॲཧ
    for (elm of array1) {
    console.log(elm)
    }
    array2.forEach((elm) => {
    console.log(elm)
    })
    array1.map((elm) => elm * 2)
    // [2, 4]
    array1.at(0)
    // 1
    #hatenaintern)*)+

    View full-size slide

  26. Arrow Function
    • function や return を使わずに関数を⽣成できる
    • 基本的にはこの⽅法で関数を⽣成しておけばハマらないBC
    const hello = name => `Hello, ${name}`
    hello("world") // hello, world
    • 引数が 1 つのときは引数を囲う () も省略可
    • Tips: 返り値がオブジェクトのときは () で囲う必要がある
    const getProps = () => ({ a: "foo", b: "bar" })
    !" 主に this が関わってくるとハマるようになる。詳細は付録「Arrow Function について」を読んでください。
    #hatenaintern)*)+

    View full-size slide

  27. Arrow Function
    • 引数が複数ある場合は () で囲う
    • 関数内の記述が複数⾏に渡るときは {} と return を⽤いる
    const hello = (name, lang) => {
    if (lang === "ja") return `͜Μʹͪ͸ɺ${name}`
    if (lang === "es") return `Hola, ${name}`
    return `Hello, ${name}`
    }
    #hatenaintern)*)+

    View full-size slide

  28. Promiseについて
    • ⾮同期処理を抽象化したオブジェクト
    • Pending(成功も失敗もしていない状態)な状態を
    表現できる
    • 成功(resolve)すれば Fulfilled、失敗(reject)
    すれば Rejected という状態になります
    • Fulfilled か Rejected のどちらかになる(つ
    まり処理が完了した)状態を Settled と呼びま
    す。
    • 成功すれば then メソッド、失敗すれば catch
    メソッド、それぞれのコールバック関数に処
    理が⾮同期に引き継がれる
    #hatenaintern)*)+

    View full-size slide

  29. const sleep = (ms) =>
    new Promise((resolve, reject) => {
    setTimeout(() => {
    if (math.random() > 0.5) {
    return reject(new Error("error"))
    } else {
    return resolve(ms)
    }
    }, ms)
    })
    sleep(1000)
    .then((ms /* resolveͨ͠஋Λड͚औΕΔ */) => console.log(`sleep: ${ms}ms`))
    .catch((e) => {
    console.error(e)
    })
    #hatenaintern)*)+

    View full-size slide

  30. fetch を使った例
    • fetch は HTTP 通信をするための API で Promise を返す
    • Promise は⾮同期なので、① が console に出⼒された後に成功/失敗それぞれの場合のメッセージが表⽰される
    /*
    Ϣʔβʔ৘ใΛऔಘ͢ΔAPIͷྫɻҎԼͷΑ͏ͳJSON͕ฦͬͯ͘Δͱ͍͏૝ఆɻ
    {
    user: {id: 1, name: 'hatena'}
    }
    */
    const promise = fetch("https://api.example.com/user/1")
    .then((res) => res.json())
    .then((json) => {
    const user = json.user
    console.log(`${user.name}ͷid͸${user.id}`)
    })
    .catch(console.error)
    console.log(promise) // Promise {} ɾɾɾ ᶃ
    #hatenaintern)*)+

    View full-size slide

  31. 複数の Promise を扱う⽅法
    Promise の配列を作成し、それを Promise.all() に渡すことで、複数の⾮同期処理を待ち合わせる。
    const promises = urls.map((url) => fetch(url)) // ෳ਺ͷAPIͳͲΛฒྻʹୟ͘
    Promise.all(promises)
    .then((responses) => {
    // ͢΂ͯͷ Promise ͕੒ޭͨ͠৔߹͜͜ʹདྷΔ
    })
    .catch(console.error)
    • Promise.all()
    • 全てが成功すれば、Resolve(全ての結果の配列)を得る。1 つでも失敗すると Reject になる。
    • Promise.allSettled()
    • 全てが完了した後に Resolve する。基本的には Reject しない。ここの Promise の実⾏結果を配列で得る
    ことが出来る。
    #hatenaintern)*)+

    View full-size slide

  32. async/await
    • async function の中であれば、await を⽤いて Promise を返す
    ⾮同期関数を同期関数のように扱えるIJ
    • エラーハンドリングする必要がある場合は try {} catch (e)
    {} を使⽤する
    !" 最近の ECMAScript の仕様に⼊っている Top-level await に対応している環境であれば async function の中で無くても await を利⽤できます
    #hatenaintern)*)+

    View full-size slide

  33. async/await
    const getUser = async (id) => {
    try {
    const res = await fetch(`https://api.example.com/user/${id}`)
    const json = await res.json()
    const user = json.user
    console.log(`${user.name}ͷid͸${user.id}`)
    return user
    } catch (e) {
    console.error(e)
    throw new Error("error reason: *********")
    }
    }
    #hatenaintern)*)+

    View full-size slide

  34. async/await
    • async function ⾃体も Promise を返す
    • Promise が返ってくる関数として、then を呼び出すことも出来る
    • つまり、呼び出す側では Promise が返ってくる関数であるという
    ことさえ分かっていれば、await で扱うことができる
    getUser(1)
    .then(console.log) // {id: 1, name: 'hatena'}
    .catch(console.error)
    #hatenaintern)*)+

    View full-size slide

  35. class 宣⾔
    • ES$%&' で class キーワードが追加された&4
    • 積極的に使うことはそんなに無いかもしれないけど、読むことは多いかもしれない
    class Rect {
    constructor(width, height) {
    this.width = width
    this.height = height
    }
    // getter΍setterΛఆٛͰ͖Δ
    get area() {
    return this.getArea()
    }
    getArea() {
    return this.width * this.height
    }
    }
    const rect = new Rect(5, 10)
    console.log(rect.area) // 50
    !" それ以前では function を使って、コンストラクタ関数を作って、プロトタイプ継承を利⽤してクラスを作っていた。class も単なるシンタックスシュガーなので、実体はコンストラクタ関
    数です。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritanceandtheprototypechain
    #hatenaintern)*)+

    View full-size slide

  36. ECMAScript Modules
    • プログラムをモジュールという単位に分割する機能
    • 1 ファイル == 1 モジュール
    • スコープはモジュールごと
    • 関数や変数などをお互いに import/export できる
    • 歴史的経緯で CommonJS_`という形式が Node.js などを中⼼に⻑く採⽤されてきたが、
    ECMAScriptxyで標準化されたモジュールの仕組みが今では Node.js、ウェブブラウザなどでも広
    くサポートされているx_
    !" 実際にはサポートしていないウェブブラウザやパフォーマンスのために Babel を使って変換した後に、モジュールを解釈して 1 つ〜複数のファイルをまとめて配信するために webpack な
    どを利⽤することが多い。詳細は付録「JavaScript をウェブアプリケーションで提供する際に使⽤するツールチェインについて」を参照してください。
    !" ECMAScript は JavaScript の仕様における名称。ECMAScript 仕様については付録「JavaScript やフロントエンド周辺技術の標準(化)について」で解説しています。
    !" module.exports という特殊なオブジェクトを経由してエクスポートし、require 関数を利⽤してインポートする⽅式。https://nodejs.org/docs/latest/api/modules.html
    #hatenaintern)*)+

    View full-size slide

  37. default export
    // module.js
    export default function doSomething() {}
    • export default はモジュールから 1 つだけエクスポートできる
    • export default でエクスポートすると、import 時には任意の名
    前を設定できる
    import awesome from "./module"
    #hatenaintern)*)+

    View full-size slide

  38. 名前付きエクスポート(named export)
    • 変数や関数に export を付加することで名前付きエクスポートが出来る
    • default export と異なり、いくつでも export できる
    // namedModule.js
    export const logType = {
    error: 'error',
    log: 'log'
    };
    export const log = (message, type) => {
    if (type === 'error') return console.error(message);
    return console.log(message);
    }
    export const hello => log('hello');
    #hatenaintern)*)+

    View full-size slide

  39. インポートの⽅法について
    • export されている名前で取り込む
    import { log, hello } from "./namedModule"
    • as でリネーム出来る
    import { logType as LOGTYPE } from "./namedModule"
    • * as で export されているもの全てをオブジェクトにする;;
    import * as Logger from "./namedModule"
    Logger.hello() // 'hello'
    !! 必要なものだけを取り込むことで受けられる恩恵(webpack による TreeShakingなど)も多いので、基本的には * as は避ける⽅のがオススメ。
    #hatenaintern)*)+

    View full-size slide

  40. Tips
    #hatenaintern)*)+

    View full-size slide

  41. for...of
    • 反復可能(iterable)なオブジェクトの要素を順番に取り出せる
    • 配列、⽂字列、NodeList、Map、Setなど
    const iterable = [10, 20, 30]
    for (const value of iterable) {
    console.log(value)
    }
    #hatenaintern)*)+

    View full-size slide

  42. Nullish coalescing operator ??
    • JavaScript では短絡評価のために || を⽤いる:;が、次のようなときに意図通りに動かない
    const rect = (width: number, height?: number) => ({
    width: width,
    height: height || 100, // ߴ͞Λলུͨ͠ͱ͖͸σϑΥϧτ஋Λ༩͑Δ
    })
    rect(50, 0) // {width: 50, height: 100}
    • 0 や ''(空⽂字)は Falsy な値12なので、短絡評価されてしまう結果、意図的に height に 0 を与えることが出来ない実装になっている。
    • ?? は左辺が null または undefined のときだけ、右辺を返す演算⼦になっているので、このようなときは ?? を代わりに⽤いることで問題を
    回避できる。
    • 基本的には ?? を使っておくのがオススメ
    !" !!0 や !!'' のように boolean に変換した時に false となる値。JavaScript ではこの他に false と null と undefined と NaN などがある。Falsy でない値は boolean に変換した時に true とな
    る。こちらは Truthy な値と呼ぶ。 https://developer.mozilla.org/en-US/docs/Glossary/Falsy
    !" JavaScript では || は左辺が Truthy!6なら左辺の値を、左辺が Falsy なら右辺の値を返す。 && はその逆で左辺が Falsy なら左辺を、左辺が Truthy なら右辺を返すが、短絡評価に使われる
    ことは少ない。
    #hatenaintern)*)+

    View full-size slide

  43. Optional chaining ?.
    • オブジェクトが null や undefined な可能性があるとき、そのオブジェクトのプロパティを呼ぶために if による分岐や && によ
    る短絡評価HIを書く必要があった。
    const val = nullOrObject && nullOrObject.method()
    const result = val && val.methodOfReturnValue()
    • ?. を⽤いると、呼び出し元が null または undefined のときはそれ以降のプロパティアクセスをしない。また、その場合は
    undefined として評価される。
    const result = nullOrObject?.method()?.methodOfReturnValue()
    nullOrObject も nullOrObject.method() の返り値が共に null でも undefined でもないときに、
    nullOrObject.method().methodOfReturnValue() の結果を得られる。
    !" && は左辺が Falsy なときは右辺を評価しないことを利⽤して、null や undefined のときは右辺を評価しないように出来る。また、&& による短絡評価は便利なものの || と同様に Falsy に関
    わる問題を時々引き起こしてしまうことに注意。この問題も Optional chaining で同時に回避できる。
    #hatenaintern)*)+

    View full-size slide

  44. Spread Syntax
    • ... を使うと配列やオブジェクトを展開出来る
    const sum = (a, b, c, d) => a + b + c + d
    const nums = [1, 2]
    const copied = [...nums] // த਎Λෳ੡ͨ͠഑ྻΛ࡞ΕΔ
    const moreNums = [...copied, 5] // [1, 2, 5]
    sum(...nums, 10) // 18
    const obj = { a: 10, b: "foo" }
    const obj2 = { b: "bar", c: true }
    // 2ͭҎ্ͷobjectΛmerge͢ΔɻΩʔ͕ॏෳ͍ͯ͠Δ৔߹͸ޙʹॻ͍ͨํͰ্ॻ͖͞ΕΔ
    const merged = { ...obj, ...obj2 } // {a: 10, b: 'bar', c: true}
    const getUserConfig = (received) => ({
    force: false,
    allowJs: false,
    ...received, // σϑΥϧτ஋Λ౉͞Εͨ஋͕͋Ε͹্ॻ͖͢Δ
    })
    #hatenaintern)*)+

    View full-size slide

  45. Rest Parameters
    • 関数の引数も ... で受け取ることで可変な⻑さの引数を受け取れる
    • Spread Syntax と違って、1 つだけ且つ引数の末尾でしか使えな

    //
    const sum = (num1, num2, ...nums) =>
    num1 + num2 + nums.reduce((a, b) => a + b, 0)
    const numbers = [1, 2, 3]
    sum(3, ...numbers, 6) // 15
    #hatenaintern)*)+

    View full-size slide

  46. TypeScript について(01min)
    #hatenaintern)*)+

    View full-size slide

  47. TypeScript is 何
    JavaScript に型アノテーションなどを付けられるようにしたプログラミング⾔語で、多くの場合は
    JavaScript に変換してから JavaScript の処理系で実⾏する。
    • node.js や React の登場などで、サーバサイドやフロントエンドを横断して JavaScript を使⽤したそこそ
    こ⼤きなウェブアプリケーションの開発が盛んに⾏われるようになった
    • そこそこの規模の⼈数でそこそこの規模の JavaScript のコードを安全に書くために型の情報を使いたい
    • 組み込みの API が何を返してくるのか。ライブラリがどういう返り値を返してくるのか。
    • ランタイムで実⾏した際に初めてランタイムエラーが起きるというのは防ぎたい。
    • Uncaught TypeError: Cannot read property 'foo' of undefined
    • そのために JavaScript に静的型付けを加えた Alternative JavaScript としての TypeScript が⽀持される
    ようになった
    #hatenaintern)*)+

    View full-size slide

  48. tsc: TypeScript compiler
    • マイクロソフトの TypeScript チームによって開発されている TypeScript を扱うためのツール
    • https://github.com/microsoft/TypeScript
    • TypeScript を JavaScript に変換(コンパイル)する^_機能とコンパイル時の静的型解析機能を提供している
    • --noEmit オプションを付けてると、静的型解析機能だけを⾛らせることができる
    • TypeScript から JavaScript への変換と⾔っても、型アノテーション等の削除がほとんど
    • JavaScript ランタイムが実⾏するときの振る舞いには影響を与えない^îと思っておいて良い
    • 多くのプロジェクトでは babel を使⽤していると思うので、@babel/preset-typescript を有効にした babel
    で変換を⾏う⽅が設定が複雑化しなかったりしてオススメ
    !" enum を使っているとコードが追加されるので影響を与える。enum は後述するオブジェクトと typeof などの組み合わせで代替可能なので、基本的には利⽤しないようにしていることが多
    い。
    !" JavaScript ランタイムが解釈できるように型情報を落として変換(コンパイル)する ≒ トランスパイラとしての役割
    #hatenaintern)*)+

    View full-size slide

  49. 型宣⾔部分を読めるようになろう
    TypeScript の代表的な表現などを紹介していきます。
    ちょっと⼿元で試したい⼈は公式の Playgroundがお⼿軽です。
    #hatenaintern)*)+

    View full-size slide

  50. 変数宣⾔時の型アノテーション
    // JavaScriptͷ৔߹
    const a = 'hello';
    // TypeScriptͷ৔߹͸ม਺໊ͱ=ͷؒʹ:Λஔ͍ͯܕΞϊςʔγϣϯΛॻ͘
    const a: ʲ͜͜ʹܕΞϊςʔγϣϯʳ = 'hello';
    // ྫ͑͹
    const a: string = 'hello';
    これくらいだったら推論してくれるので、実際には書かないこと
    も多い
    #hatenaintern)*)+

    View full-size slide

  51. 代表的な表現 ①
    • プリミティブ型: string, number, boolean, null, undefined
    • 'hello', 12, true, false のような特定の値(リテラル型と呼びます)も使える
    const a: number = 10
    const b: boolean = false
    const c: string = 11 // Type Error
    const d: "hello" = "hello"
    const n: null = null
    • 配列
    const arr: string[] = ["hello", "world"]
    const arr2: Array = [1, 2, 3, 5, 8]
    const arr3: [string, number] = ["year", 2021] // λϓϧ(Tuple)ܕͱ΋
    #hatenaintern)*)+

    View full-size slide

  52. 代表的な表現 ②
    • オブジェクト
    • JavaScript のオブジェクト同様に書いて、値を書くところに型を書く
    • キー名に ? を付けるとオプショナルなキーになって、省略可能になる。ST
    const person: {
    name: string
    age: number
    address?: string
    } = {
    name: "john",
    age: 21,
    }
    !"
    string | undefined のような記述と同じと紹介されることもある。値が⼊っているかどうかで JavaScript として実⾏した際の振る舞いが変わることがある(Object.keys() など)ので、厳密
    には同じではないことに注意。特に TypeScript ^.^ で導⼊された exactOptionalPropertyTypes を有効にすると、tsc での型解析時の振る舞いも変わります。
    #hatenaintern)*)+

    View full-size slide

  53. type
    type を使うと型表現にエイリアスを付けられる
    type Person = {
    name: string
    age: number
    }
    type Team = Person[]
    #hatenaintern)*)+

    View full-size slide

  54. Union Type (合併型)
    複数の型のいずれかを満たす
    type Primitive = string | number | boolean | undefined | null
    type Color = "red" | "green" | "blue" | "yellow" | "purple"
    const a: Primitive = "hello"
    const b: Primitive = 10
    const c: Color = "red"
    const d: Color = "black" // Type Error
    #hatenaintern)*)+

    View full-size slide

  55. 型ガード(Type Guard)に使える便利な
    JavaScript の演算⼦
    JavaScript の演算⼦の中には有効に使うことで、静的解析時に
    TypeScript コンパイラによって便利に使⽤されるものがある。
    typeof と in をここでは紹介します。これらは JavaScript のラン
    タイム上で動作することに注意。
    #hatenaintern)*)+

    View full-size slide

  56. typeof 演算⼦
    • 値の型(ここでの"型"は JavaScript ランタイム上での型)を 'string',
    'number', 'boolean', 'object', 'function', 'undefined' から返す
    console.log(typeof "hello world") // 'string'
    const n = 10
    console.log(typeof n) // 'number'
    const p: Person = { name: "jonh", age: 20 }
    console.log(typeof p) // 'object'
    console.log(typeof undefined) // 'undefined'
    console.log(typeof null) // 'object'
    console.log(typeof ["a"]) // 'object'
    console.log(Array.isArray(["a"])) // true
    #hatenaintern)*)+

    View full-size slide

  57. typeof 演算⼦の利⽤例
    • 特に number や string であることに制限したいときに頻出
    const func = (val: string | number) => {
    // Property 'toUpperCase' does not exist on type 'string | number'.
    // Property 'toUpperCase' does not exist on type 'number'.
    val.toUpperCase()
    if (typeof val === "string") {
    // ͜͜Ͱ͸val͸stringܕ
    return val.toUpperCase()
    }
    // ͜͜Ͱ͸val͸numberܕ
    return val.toFixed(2)
    }
    #hatenaintern)*)+

    View full-size slide

  58. in 演算⼦
    値に特定のプロパティが有ることを判定する演算⼦。最近はブラウザが特定の API に対応しているかどうかを識別することにも使われる。
    type Fish = {
    name: string
    swim: () => void
    }
    type Bird = {
    name: string
    fly: () => void
    }
    const move = (x: Fish | Bird) => {
    if ("swim" in x) {
    // swim͕༗Δͷ͸FishܕͷΈ
    return x.swim()
    }
    // ͳͷͰɺ͜͜ʹ౸ୡ͢Δͱ͸BirdܕͰ͋Δͱ෼͔Δ
    return x.fly()
    }
    #hatenaintern)*)+

    View full-size slide

  59. Tagged Union Types で型ガードする
    • type や kind のようなプロパティにリテラル型を設定しておいて、その中⾝を === や switch を使って⽐較することで、型の絞り込みを⾏う
    • 個⼈的な感覚だと、in での絞り込みよりもこちらのパターンの⽅がよく利⽤する気がします
    • リテラル型の⽐較の⽅が書くのが簡単で、かつこちらのほうがより安全です。
    type Fish = {
    kind: "fish"
    name: string
    swim: () => void
    }
    type Bird = {
    kind: "bird"
    name: string
    fly: () => void
    }
    const move = (x: Fish | Bird) => {
    if (x.kind === "fish") {
    return x.swim()
    }
    return x.fly()
    }
    #hatenaintern)*)+

    View full-size slide

  60. as を⽤いた型アサーション(Type Assertion)
    • TypeScript によって推論された型を上書きしたいときに使う
    • 型キャストではない(ランタイム上での振る舞いがなんら変わ
    ることはない)
    • 多くの場合は害になるので、本当に必要な場合だけ利⽤する
    • 例えば、古い JavaScript のコードを移植するなど
    #hatenaintern)*)+

    View full-size slide

  61. as を⽤いた型アサーション(Type Assertion)
    // ܕFooΛ௥Ճ͢Δ
    type Foo = {
    bar: number
    piyo: string
    }
    const something = (x: Foo) => {
    // ܕͱͯ͠͸߹͍ͬͯΔ͕ɺϥϯλΠϜ্Ͱͷ࣮ߦ࣌ʹ͸piyo͕undefinedʹͳΔͷͰΤϥʔ͕ى͖Δ
    return x.piyo.split(",")
    }
    const foo = {} as Foo // Fooͱͯ͠ѻ͑ΔΑ͏ʹ͓ͯ͘͠
    // ࣮ࡍʹ͸barͳͲ͸ແ͍͕Fooͱͯ͠Ξαʔγϣϯ͍ͯ͠ΔͷͰ౉ͤΔ
    something(foo)
    #hatenaintern)*)+

    View full-size slide

  62. const アサーション
    as const とすることで変数代⼊時などに変更不可能としてアサーションしてくれる。
    const a = [1, 2, 3] // aͷܕ͸number[]ͱͳΔ
    const b = [1, 2, 3] as const // bͷܕ͸readonly [1, 2, 3]ͱͳΔ
    // readonly ͳ഑ྻʹ͸ push ΍ pop ͳͲͷมߋΛՃ͑Δϝιου͕ଘࡏ͠ͳ͍
    a.push(4) // OK
    b.push(4) // NG
    type Pallet = {
    colors: Color
    }
    const setPallet = (p: Pallet) => {
    /* do something */
    }
    const pallet = {
    color: "red",
    } // ͜͜ʹ as const Λ෇͚ͳ͍ͱ{ color: string }ͱਪ࿦͞ΕͯΤϥʔʹͳΔ
    setPallet(pallet)
    #hatenaintern)*)+

    View full-size slide

  63. any と unknown
    TypeScript 上で不定な型を扱うための⽅法を紹介します。
    #hatenaintern)*)+

    View full-size slide

  64. any
    • 何らかの値が⼊っていることを⽰す。undefined からオブジェク
    トから関数まで何が⼊っていても良い。tsc が型の検証をしな
    いので、as 同様に避けられる場合は避ける。
    let anything: any = {}
    // anyʹ͸ԿͰ΋୅ೖͰ͖Δ
    anything = () => {}
    anything = null
    anything.split(",") // anyͷ৔߹͸ϝιου΋ͳΜͰ΋ࢀরͰ͖Δ
    #hatenaintern)*)+

    View full-size slide

  65. unknown
    • any 同様に何らかの値が⼊っている型。
    • any と違い、unknown はメソッドにアクセスしようとすると検証時にエラーになる。
    • unknown ≒ {} | null | undefined
    • 利⽤時に型ガードをして型を絞り込む
    const getObjectValues = (obj: {}) => Object.values(obj)
    // ݺͼग़͠ଆ͸unknownͳͷͰ޷͖ͳ஋Λ౉ͤΔ
    const stringifyForLog = (val: unknown) => {
    if (val === null || val === undefined) return "(anonymous)"
    return JSON.stringify(getObjectValues(val))
    }
    #hatenaintern)*)+

    View full-size slide

  66. type と interface
    • type はエイリアス
    • interface はオブジェクトに型を付ける別の⽅法。
    • 既存のものに後からプロパティを追加できるのは interface
    • ライブラリが提供した interface を利⽤者が⾃由に拡張できる
    • type は別の名前を付ける必要がある
    • type と interface の使い分けはコード規約などで⾊々な流派や主張があ
    るので、郷に⼊れば郷に従ってください
    #hatenaintern)*)+

    View full-size slide

  67. type と interface
    Type
    • Type は同じ型定義名での拡張ができない
    type Blog = {
    title: string
    content: string
    }
    // NG: Duplicate identifier 'Blog'.
    type Blog = {
    tags: string[]
    }
    // OK
    type NewBlog = Blog & {
    tags: string[]
    }
    Interface
    • Interface は拡張可能
    • 例えば
    • ES5655 では、Array に at() メソッドが追加された
    • TypeScript I.K での型定義を確認すると、 実際に Array 型を拡張
    している
    // lib.es5.d.ts
    interface Array {
    length: number
    toString(): string
    ...
    }
    // lib.es2022.array.d.ts
    interface Array {
    at(index: number): T | undefined
    }
    #hatenaintern)*)+

    View full-size slide

  68. 関数
    既にサンプルでは何度も出てきているけど、引数や返り値の型の書き⽅のパターンたち紹介しておきます。
    const f = (x: string): number => {
    return x.length
    }
    // ಛʹreturnΛ͠ͳ͍৔߹͸ฦΓ஋ʹvoidΛࢦఆ͢Δ
    const a: () => void = () => {
    console.log("a")
    }
    // ΦϓγϣφϧͳҾ਺͸keyʹ?Λ෇͚Δ
    // ਪ࿦͞ΕΔ΋ͷͰྑ͍ͳΒฦΓ஋ͷܕ͸লུՄ
    const b = (n?: number) => `${n}`
    // Rest ParametersΛड͚औΔ৔߹͸͜͏͍͏ײ͡
    const c = (...texts: string[]) => {
    return texts.join("|")
    }
    #hatenaintern)*)+

    View full-size slide

  69. 型引数(Generics)
    • 関数の返り値の型に関する制約を外から与えて、関数内部で利⽤できる。
    • よくよく型定義などを⾒ると定義されていて利⽤可能だけど、気付いていないということもよくある…
    • TypeScript で querySelector メソッドを使うときに型引数を指定する - Hatena Developer Blog
    const getJSON = (url: string): Promise => {
    // res.json͸anyͱͳΒͣʹܕҾ਺Ͱ౉͞Εͨ΋ͷͱղऍ͞ΕΔ
    return fetch(url).then((res) => res.json())
    }
    // ͜͜Ͱusers͸User[]ʹͳΔ
    const users = await getJSON("/api/users")
    // ͜͜Ͱblogs͸Blog[]ʹͳΔ
    const blogs = await getJSON("/api/blogs")
    #hatenaintern)*)+

    View full-size slide

  70. 続: 型引数
    • extends を使うと指定した型/インターフェースを満たすように指定できる
    • 型引数をそのまま関数の引数の型に使うことで静的解析時に呼び出し元の引
    数の型から返り値を推論してくれる
    const echo = (text: T): T => {
    return text
    }
    const a = echo("foo") // a ͷܕ͸ 'foo'
    const str: string = "foo"
    const b = echo(str) // b ͷܕ͸ 'string'
    #hatenaintern)*)+

    View full-size slide

  71. never
    • 絶対に発⽣‧到達しないことを表す型
    • 例えば無限ループがある関数は絶対に完了しない関数なので返り値は never
    になる
    • void は代⼊可能MNだが、never には never のみ代⼊可能(つまり変数には基
    本的に代⼊出来ずにエラーになる)
    const infiniteLoop = (): never => {
    while (true) {}
    }
    !" strictNullChecking が有効になっていない場合のみ代⼊可能。⼀⽅で JavaScript のランタイム上では undefined なので、代⼊することはほとんどないでしょう。
    #hatenaintern)*)+

    View full-size slide

  72. never を⽤いた網羅性チェック
    • never を⽤いることで型ガードなどでの網羅性をチェックできる
    type Color = "red" | "yellow" | "purple"
    const magical = (color: Color) => {
    switch (color) {
    case "red":
    return "tomato"
    case "yellow":
    return "banana"
    default:
    // શͯͷcase͕໢ཏ͞Ε͍ͯΕ͹͜͜ʹ౸ୡ͢Δ͜ͱ͸ͳ͍
    // ͜ͷ৔߹͸'purple'͕୅ೖ͞ΕΔՄೳੑ͕͋ΔͷͰɺ੩తղੳ࣌ʹΤϥʔʹͳͬͯݕग़Ͱ͖Δ
    const val: never = color
    throw new Error(`"${color}" is not implemented`)
    }
    }
    #hatenaintern)*)+

    View full-size slide

  73. ざっとだけ眺めるコーナー
    • ここまでを理解したときに読むと便利なコーナーです
    • ちょっとしたテクニックと合わせて書いておきます
    #hatenaintern)*)+

    View full-size slide

  74. Readonly / ReturnType
    • Readonly はオブジェクトや配列の要素を読み込み専⽤にできる
    • 再帰的には適⽤されないことに注意
    type PersonRo = Readonly
    • ReturnType は関数の返り値型として得る
    type Func = () => string
    type ReturnVal = ReturnType // ReturnVal͸stringͱղऍ͞ΕΔ
    #hatenaintern)*)+

    View full-size slide

  75. typeof 演算⼦
    • こちらは前述のものとは違うTypeScript 組み込みのもの。型ア
    ノテーションを書く場所で利⽤する。
    • JavaScript で宣⾔された値を静的解析して型を得る
    const hello = () => "hello"
    type Func = typeof hello
    type P = ReturnType // P͸stringͱղऍ͞ΕΔ
    #hatenaintern)*)+

    View full-size slide

  76. keyof 演算⼦
    オブジェクトの key を列挙して union type として得られる
    const config = {
    checkJs: false,
    force: true,
    }
    // typeofͰconfigͷܕΛಘͯɺkeyofͰͦͷΦϒδΣΫτͷܕͷΩʔΛྻڍ͢Δ
    type ConfigKey = keyof typeof config // "checkJs" | "force"
    const getConfigVal = (key: ConfigKey) => config[key]
    getConfigVal("ignore") // Τϥʔͱͯ͠ݕग़Ͱ͖Δ
    #hatenaintern)*)+

    View full-size slide

  77. Indexed Access Types
    JavaScript で配列やオブジェクトに [] を使って値を取り出すように型でも同
    じようなことが出来る。typeof や keyof などと組み合わせることで
    JavaScript で定義した配列やオブジェクトの値から列挙した型などを⽣成で
    きる。
    type Person = {
    name: string
    age: number
    }
    type Age = Person["age"] // number
    const signalColors = ["red", "blue", "yellow"] as const // as const͠ͳ͍ͱstring[]ʹͳΔ
    // Arrayʹ[number]ͰΞΫηε͢Δͱ഑ྻͷ஋Λྻڍͨ͠ܕΛಘΒΕΔ
    type Signal = typeof signalColors[number] // 'red' | 'blue' | 'yellow'
    #hatenaintern)*)+

    View full-size slide

  78. 交差型(Intersection Types)
    複数の型を組み合わせて型を⽣成する。例えばユーザーの権限に
    応じてレスポンスの型を変える場合はこういう感じ。
    type Blog = { title: string; domain: string }
    type Editor = { editable: true; authority: ["edit"] }
    type Owner = { editable: true; authority: ["edit", "publish"] }
    type ResponseForEditor = Blog & Editor
    type ResponseForOwner = Blog & Owner
    #hatenaintern)*)+

    View full-size slide

  79. Conditional Types
    JavaScript の三項演算⼦と同じことが型表現の中でも出来る。
    condition ? trueExpression : falseExpression // JavaScriptͷࡾ߲ԋࢉࢠ
    // SomeType͕OtherTypeΛຬͨͤ͹TrueTypeΛಘΔ
    SomeType extends OtherType ? TrueType : FalseType;
    Overloads を使わずに関数の引数に応じて返り値の型を変える
    declare function getID(
    fancy: T
    ): T extends true ? string : number
    const stringReturnValue = getID(true)
    const numberReturnValue = getID(false)
    const stringOrNumber = getID(Math.random() < 0.5)
    #hatenaintern)*)+

    View full-size slide

  80. Overloads
    • 関数が引数の数や型などに依って振る舞いが変わることを記述する⽅法
    • 引数と返り値を複数宣⾔した後に実装を書く
    • 最後の実装は全ての Overloads を満たす必要がある
    function request(url: string): Promise
    function request(url: string, onlyIsOk: true): Promise
    function request(url: string, onlyIsOk = false) {
    const promise = fetch(url)
    if (onlyIsOk) return promise.then((res) => res.ok)
    return promise
    }
    #hatenaintern)*)+

    View full-size slide

  81. Overloads と関数の型宣⾔
    • 基本は短く書くのを使っておけば良いです
    type f = (x: number) => number
    • 同様のことをこのようにも書ける
    type f = {
    (x: number): number
    }
    • Overloads を型宣⾔と共に書きたい場合は後者を使う
    type func = {
    (x: number): number
    (x: string): string
    }
    #hatenaintern)*)+

    View full-size slide

  82. React について(,-min)
    #hatenaintern)*)+

    View full-size slide

  83. この章では React に関する最低限の読み書きが出来るようになる
    ことを⽬指します。
    独りで開発していても、数千の開発者と共同開発していても、
    React の開発体験は同じです。個⼈、チーム、⼤規模な組織によっ
    て書かれさまざまなコンポーネントを、シームレスに組み合わせ
    ながら開発できる。それが React の設計理念です。
    https://ja.react.dev/
    #hatenaintern)*)+

    View full-size slide

  84. イメージしてみる
    さて、⽂字だけでは想像しにくいので実際のコードを⾒ながら説明していきたいと思います。
    例えば、以下のような TODO アプリを作ろうとします。
    #hatenaintern)*)+

    View full-size slide

  85. 素の JavaScript
    #hatenaintern)*)+

    View full-size slide

  86. 素の JavaScript
    (動的⽣成)の問題点
    • どういう成果物が⽣成されるのかイメ
    ージしづらい
    • UI の追加や⽣成がその場その場で書か
    れがちで集約化が難しくなりがち
    • テストやその他設計上の⼯夫なども難
    しくなる
    #hatenaintern)*)+

    View full-size slide

  87. React
    #hatenaintern)*)+

    View full-size slide

  88.    React
    (宣⾔的 UI)の利点
    • UI 部分を宣⾔的に記述する⽅法のこと
    • ウェブアプリケーションのリッチ化や
    スマートフォンアプリの登場で、GUI
    を動的に構築‧変更する重要度と求め
    られる GUI の複雑性が格段に向上した
    という歴史がありました
    #hatenaintern)*)+

    View full-size slide

  89. 魂が震える&'仮想(Virtual) DOM
    • React の内部では実際の DOM23ではなく、DOM と対になる単純な構造体を持っている。これが仮想 DOMと呼ば
    れている。
    • React では状態の変更を検知すると、変更前後の仮想 DOM の差分を計算し、その差分がある部分だけを実際の
    DOM に適応する。
    • ブラウザのレンダリングコストを抑えつつも、開発者は UI をそのまま記述するだけで良いという仕組みを実
    現している。
    • リストなどで順番が⼊れ替わる際などは key という属性を与えることでその⼦要素が同じであることを⽰すこと
    が出来る
    https://ja.reactjs.org/docs/reconciliation.html
    !" Document Object Model の略。HTML や XML ⽂書の構造を操作するためのプログラミングインターフェイスのこと。
    !" https://zenn.dev/mizchi/books/"c66c7!"f6cc96:c!;b<
    #hatenaintern)*)+

    View full-size slide

  90. React の書き⽅‧読み⽅
    #hatenaintern)*)+

    View full-size slide

  91. JSX
    JSX は JavaScript の拡張構⽂
    My name is Clementine!
    • React DOM は HTML の属性名ではなく、キャメルケースの命名
    規則を使⽤します。(aria-* や data-* 属性は例外です。)
    • class も className と記述されますが、これは class が
    JavaScript において予約語であるためです。
    #hatenaintern)*)+

    View full-size slide

  92. クラスコンポーネントと関数コンポーネント
    React ではコンポーネントの書き⽅が 2 種類あります。

    クラスコンポーネント
    class HelloMessage extends React.Component {
    render() {
    return Hello {this.props.name}
    }
    }
    関数コンポーネント
    const HelloMessage = ({ name }) => {
    return Hello {name}
    }
    #hatenaintern)*)+

    View full-size slide

  93. クラスコンポーネントと関数コンポーネント
    関数コンポーネントを使⽤することが推奨されている。
    クラスコンポーネント
    React アプリでのエラーを扱うのに Error
    Boundary という仕組みで使うこともある。
    関数コンポーネント (Function Component)
    • React Component は関数を⽤いて表現すること
    で関数型プログラミングの概念を利⽤できるよ
    うにしている
    • UI = f(state)
    • Presenter/View などの層に分けた後に、それら
    を組み合わせた合成関数として React
    Component が表現出来る
    • Unit Test などが簡単になった
    #hatenaintern)*)+

    View full-size slide

  94. Function Component と TypeScript
    • TypeScript で JSX を記述する場合は拡張⼦を.tsxにする
    • 型推論に任せると () => JSX.Elementになる。保守性などを考
    えるとReact.FC を明⽰するのが良いOP
    type Props = { name: string }
    const Welcome: React.FC = ({ name }) => {
    return Welcome {name}
    }
    !" React Component として不正なundefinedを返すことなどを検出してくれます
    #hatenaintern)*)+

    View full-size slide

  95. Props と State
    • React Component には値を持つ⽅法が⼤きく 2 つある
    • 関数の引数として受け取るPropsと内部状態を保持するState
    #hatenaintern)*)+

    View full-size slide

  96. Props を渡す/受け取る
    • 受け取る側は関数の第 1 引数でオブジェクトとして受け取る
    type Props = { name: string }
    const Welcome: React.FC = ({ name }) => {
    return Welcome {name}
    }
    • 渡す側(親側)は JSX で属性値として渡す。オブジェクトのキーと値がそ
    れぞれ属性名と値に対応する

    // Welcome John
    #hatenaintern)*)+

    View full-size slide

  97. Function Component と Hooks
    • Hooks は React -..0(2019 年)から追加された機能。
    • それまでは関数コンポーネントは、SFC ( Stateless Functional
    Component ) と呼ばれていた。
    • 関数コンポーネントに状態を持つことができるようになった。
    #hatenaintern)*)+

    View full-size slide

  98. 状態(State)を扱う
    • useStateという特殊な関数
    を使うことで状態を持つこ
    とが出来る
    • こういったuseから始まる関
    数は React でフック
    (Hooks)と呼ばれる特別な
    関数
    const Counter = () => {
    const [count, setCount] = useState(0)
    const increaseCount = ()
    => setCount((prevCount) => prevCount + 1)
    return (

    Χ΢ϯτ: {count}
    Χ΢ϯτ

    )
    }
    #hatenaintern)*)+

    View full-size slide

  99. Hooks の掟
    Rules of Hooks ‒ React
    • 名前はuseから始める
    • トップレベルで呼ぶ
    • ifの中などで呼ばない
    • early return する前に必ず呼ぶ
    これらはeslint-plugin-react-hooksで検出してくれるように出来る
    #hatenaintern)*)+

    View full-size slide

  100. 代表的な組み込み Hooks の紹介
    #hatenaintern)*)+

    View full-size slide

  101. useState
    • useState()で初期値を与えることが出来、返り値のタプルの 1 つ⽬が
    現在の値で、2 つ⽬が setter になっている
    • 返り値がタプル(配列)なので、好きな名前をつけるのが簡単
    • setter を呼ぶと内部状態が更新されたことが Component に通知さ
    れて、仮想 DOM の再⽣成、⽐較、レンダリングの更新が⾏われる
    • 推論できないものを型指定したい場合は型引数を⽤いることが出来る
    const [color, setColor] = useState("red")
    #hatenaintern)*)+

    View full-size slide

  102. useStateの setter について
    • 新しい値を渡す
    const [color, setColor] = useState("red")
    const change2Blue = () => setColor("blue")
    • 直前の値を利⽤して新しい値を決定する
    const [count, setCount] = useState(0)
    const increaseCount = () => setCount((prevCount) => prevCount + 1)
    #hatenaintern)*)+

    View full-size slide

  103. useEffect
    • React Component 内外部システムと同期を⾏うためのフック
    • 例えば
    • API からデータを取得して Component の状態を更新する
    • イベントハンドラを登録する
    • jQuery のコードを呼び出すなど
    #hatenaintern)*)+

    View full-size slide

  104. setInterval でタイマーと同期する
    const Timer = () => {
    const [timer, setTimer] = useState(0)
    setInterval(() => {
    setTimer((prevTimer) => prevTimer + 1)
    }, 1000)
    return ܦա࣌ؒ: {timer}
    }
    • コンポーネントがレンダリングされるたびにsetIntervalが呼ばれてしまう
    #hatenaintern)*)+

    View full-size slide

  105. useEffectの中でsetIntervalを呼ぶ
    const Timer = () => {
    const [timer, setTimer] = useState(0)
    useEffect(() => {
    setInterval(() => {
    setTimer((prevTimer) => prevTimer + 1)
    }, 1000)
    }, [])
    return ܦա࣌ؒ: {timer}
    }
    • useEffect の依存配列に空配列を渡すことで、Component のマウント時にのみ実⾏される
    ようになる
    #hatenaintern)*)+

    View full-size slide

  106. useEffectと依存配列
    • 依存配列で副作⽤のタイミングをコントロールできる
    • 第 2 引数に依存を表す配列を渡すことができる
    • Component のマウント時
    • useEffect(೚ҙͷॲཧؔ਺, [])
    • 空の配列を渡すことで、マウント時に副作⽤を実⾏できる
    • ある state などが更新された際に副作⽤を呼び出すには?
    • useEffect(೚ҙͷॲཧؔ਺, [state])
    • 副作⽤に関連する state の配列を渡すことで Component の状態に応じて副作⽤を実⾏できる
    #hatenaintern)*)+

    View full-size slide

  107. タイマーのカウント数を変更する例
    const Timer = () => {
    const [timer, setTimer] = useState(0)
    const [count, setCount] = useState(1)
    useEffect(() => {
    setInterval(() => {
    setTimer((prevTimer) => prevTimer + count)
    }, 1000)
    }, [])
    return (
    <>
    setCount(c => c + 1)}>
    Χ΢ϯτ਺Λ૿΍͢ {count}

    ܦա࣌ؒ: {timer}
    >
    )
    }
    count を増やしても timer の増加数は変わらない。
    #hatenaintern)*)+

    View full-size slide

  108. useEffectと依存配列
    • 依存配列を設定することで、それぞれの依存配列内のいずれかの値が変更されたとき>?のみ副作⽤が呼び出されるように出来る
    useEffect(() => {
    const id = setInterval(() => {
    setTimer((prevTimer) => prevTimer + count)
    }, 1000)
    return () => {
    clearInterval(id)
    }
    - }, [])
    + }, [count])
    • 依存配列は中⾝が空の配列[]を指定すると、Component のマウント時@Aに限定することが出来る
    !" Component に対応した DOM が挿⼊(初回描画)されることをマウント(mount)、その DOM が削除されることをアンマウント(unmount)と呼びます
    !" 変更されたことを検知する⽐較の詳細については付録「Hooks の依存の⽐較とオブジェクトの同⼀性について」を参照
    #hatenaintern)*)+

    View full-size slide

  109. useEffect とクリーンナップ
    • useEffect は関数を返すことでその関数が次の副作⽤が呼び出される前:;に実⾏される
    • これを利⽤すると副作⽤のクリーンナップが出来る
    前回の setInterval の例をクリーンナップを追加すると以下のようになる
    useEffect(() => {
    const id = setInterval(() => {
    setTimer((prevTimer) => prevTimer + count)
    }, 1000);
    return () => {
    // clearInterval ͰλΠϚʔΛఀࢭ͢Δؔ਺
    clearInterval(id)
    }
    }, [count])
    !" 空配列を指定している場合などはアンマウント時にも実⾏される
    #hatenaintern)*)+

    View full-size slide

  110. 独⾃フック(Custom Hook)
    • use から名前が始まり、内部で他の Hook を呼び出せる関数のこと
    • 複数の Hooks を組み合わせたり、Component の振る舞いを共通化して、1 つの関数に切り出すときなどに利⽤する
    const useGetStatus = ({ userId }) => {
    const [status, setStatus] = useState(null)
    useEffect(() => {
    const handler = (user) => {
    setStatus(user.status)
    }
    Api.subscribe(userId, handler)
    return () => Api.unsubscribe(userId, handler)
    })
    return status
    }
    #hatenaintern)*)+

    View full-size slide

  111. 独⾃フックについての Tips
    • 独⾃フックに Component の役割を共通化することで切り出した機能のみをテスト可能になる
    • 独⾃フックで返すオブジェクトや関数などは useState や useMemo、useEffect、useCallback で
    同⼀性を担保しておく
    • 特に関数についてはうっかり素朴に関数オブジェクトを返してしまいがちなので、気にしておく
    と吉ij
    • 独⾃フックを呼び出す側が同⼀性を保持するためにメモ化する(ことを検討する)必要が出てき
    てしまう
    • 結果、そのままでは利⽤できずに useEffect の依存配列に渡すこととなり、結果的に再利⽤性
    も下がってしまう
    !" useCallback はとにかく使え! 特にカスタムフックでは - uhyo/blog
    #hatenaintern)*)+

    View full-size slide

  112. お疲れさまでした
    • TypeScript と React についてザッと概観についてお伝えしました
    • これだけで皆さんが書くのは難しいかもしれませんが、
    TypeScript や React に挑戦するきっかけになってくれればと思っ
    ています
    • JavaScript やフロントエンドの世界は更に広がっています。ウェ
    ブブラウザを中⼼にあらゆるところでユーザーの⽬に直接触れる
    ことの多いフロントエンドの世界を楽しんでください。
    #hatenaintern)*)+

    View full-size slide

  113. 付録
    本編に⼊り切らなかった踏み込んだ補⾜や解説について書
    いています。興味があれば読んでください的なコーナーで
    す。
    ⽬次
    • Arrow Function について
    • useState の state を更新する際の注意
    • Hooks の依存の⽐較とオブジェクトの同⼀性について
    • useMemo や useCallback を⽤いたパフォーマンス改善
    • React Component 内で DOM にアクセスする
    • JavaScript をウェブアプリケーションで提供する際に使
    ⽤するツールチェインについて
    • JavaScript やフロントエンド周辺の主なツールについて
    • JavaScript やフロントエンド周辺技術の標準(化)につい

    #hatenaintern)*)+

    View full-size slide

  114. Arrow Function に置き換え出来ないケース
    • function を使ってコンストラクタ関数にしている(new している)
    • arguments を参照している
    • this を参照している
    • このケースについて解説します
    #hatenaintern)*)+

    View full-size slide

  115. Arrow Function と this
    • Arrow Function と function キーワードで⽣成した関数とでは
    主に this の扱いが⼤きく異なる
    • このことによって単純な置き換えが不可な場合がある
    #hatenaintern)*)+

    View full-size slide

  116. this のスコープの違いについて
    • function を⽤いた関数の場合
    const person = {
    name: "chris",
    say: function () {
    setTimeout(function () {
    console.log(`I'm ${this.name}`)
    }, 100)
    },
    }
    person.say() // I'm
    • 関数の中の this は呼び出し元のオブジェクトになる。この場合は window.setTimeout(window は省略できる) からの
    呼び出しなので、 window になっている
    • https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/
    setTimeout#thethisproblem
    #hatenaintern)*)+

    View full-size slide

  117. this のスコープの違いについて
    • Arrow Function だとスコープが外と同じになる
    const person = {
    name: "chris",
    say: function () {
    setTimeout(() => {
    console.log(`I'm ${this.name}`)
    }, 100)
    },
    }
    person.say() // I'm chris
    #hatenaintern)*)+

    View full-size slide

  118. useState の state を更新する際の注意
    新しい値を渡すときの落とし⽳
    const [count, setCount] = useState(0)
    const increaseCount = () => setCount(count + 1)
    としてしまうと、
    const increaseDouble = () => {
    increment()
    increment()
    }
    のようなものを作ったときに、increaseDouble を呼んでも 1 しか増えないという現象に遭遇するでしょ
    う。
    #hatenaintern)*)+

    View full-size slide

  119. 関数内の変数スコープと useState
    例えば、count が 5 であるとすると
    const Component = () => {
    const [count, setCount] = useState(0) // ͜͜Ͱม਺count͸είʔϓ಺Ͱݻఆ͞ΕΔ(5)
    const increaseCount = () => setCount(count + 1) // ↑Ͱݻఆ͞Εͨcount + 1(=6)ΛsetCountʹ౉͢
    const increaseDouble = () => {
    increment() // ↑Ͱ࡞ͬͨؔ਺ΛݺͿͱɺ6͕setCountʹ౉͞ΕΔ
    increment() // ͜ͷؔ਺ΛݺͿͱ͖΋ɺ6͕setCountʹ౉͞ΕΔͷͰɺ஋͸6ͷ··
    }
    }
    #hatenaintern)*)+

    View full-size slide

  120. コールバック関数を渡す⽅法で書き直す
    例えば、count が 5 であるとすると
    const Component = () => {
    const [count, setCount] = useState(0) // ͜͜Ͱม਺count͸είʔϓ಺Ͱݻఆ͞ΕΔ(5)
    const increaseCount = () => setCount((prevCount) => prevCount + 1) // prevCount͸ݺͼग़࣌͠ͷ௚લͷ஋
    const increaseDouble = () => {
    increment() // ͜͜ͰݺͿͱɺprevCountʹ͸5͕ೖ͍ͬͯΔͷͰɺprevCount+1=6͕setCount͞ΕΔ
    increment() // ͜͜ͰݺͿͱɺprevCountʹ͸6͕ೖ͍ͬͯΔͷͰɺprevCount+1=7͕setCount͞ΕΔ
    }
    }
    更新後の state の値が更新前の値に依存している場合は、コールバッ
    ク関数を渡す形式を使うようにしましょう。
    #hatenaintern)*)+

    View full-size slide

  121. Hooks の依存の⽐較とオブジェクトの同⼀性
    について
    プリミティブな値のときは === で⽐較されるが、オブジェクトや配列は Object.is で⽐較され
    る。つまり、中⾝が同じオブジェクトなだけでは異なる値として認識されることに注意。
    const a = "foo"
    const b = "foo"
    console.log(a === b) // true
    const objA = { a: "foo", b: 10 }
    const objB = { a: "foo", b: 10 }
    console.log(objA === objB) // true
    console.log(Object.is(objA, objB)) // false
    #hatenaintern)*)+

    View full-size slide

  122. 依存配列にオブジェクトを⼊れるケースについて
    const config = { theme: "sports" }
    useEffect(() => {
    loadConfig(config).then(() => {})
    }, [config])
    のような場合にはレンダリングの度に、config が再⽣成される。よって、
    異なる値として認識されてしまい、毎回副作⽤が呼び出されてしまう。こ
    のような例の場合は依存に [config.theme] という⾵に値を書いてしまっ
    ても良いが、依存するオブジェクトについて知っている必要があるので難
    しい。
    #hatenaintern)*)+

    View full-size slide

  123. シンプルな回避策
    • ⼀番簡単な回避策は Component の外で初期化してしまえば良い
    const config = { theme: "sports" }
    function Component() {
    useEffect(() => {
    loadConfig(config).then(() => {})
    }, [config])
    }
    • ⼀⽅で、この世には Props を利⽤してオブジェクトを⽣成するなどもよ
    くあるので、この⽅法が使えることは少ない
    #hatenaintern)*)+

    View full-size slide

  124. オブジェクトの再⽣成を回避するために useMemo を利⽤
    する
    • useMemo は React に組み込まれている Hooks の 1 つで、その名の通り、値をメモ化DEすることが出来ます
    英⽂章を⼦要素に持ち+,、その⽂章中の単語数を数える Component を書いてみる
    function WordCount({ children }) {
    // text͸stringͳͷͰɺͦͷ··ґଘ഑ྻʹग़དྷΔ
    const words = useMemo(() => children.split(" "), [text])
    useEffect(() => {
    alert(`୯ޠ਺͸${words.length}Ͱ͢`)
    }, [words])
    }
    !" Component の中の⼦要素は children という名前で受け取ることが出来る。Lorem ipsum dolor sit amet のような形で呼び出す。
    !" メモ化はパフォーマンス改善のために計算結果をキャッシュしたりすること
    #hatenaintern)*)+

    View full-size slide

  125. useCallback で関数をメモ化する
    • 値同様に関数をメモ化したい場合は useCallback を利⽤する
    • メモ化しないと毎レンダリング時に関数オブジェクトが⽣成
    されてしまう
    const handler = useCallback((val) => alert(val), [])
    useEffect(() => {
    Api.notification.subscribe(handler)
    }, [handler])
    #hatenaintern)*)+

    View full-size slide

  126. useMemo や useCallback を⽤いたパフォーマ
    ンス改善
    • useMemo や useCallback は値や関数のメモ化によって useEffect などの不要な呼び出しを抑制することによってパフォーマン
    スの改善を期待できる
    • 特に useMemo では依存に使わない場合でも、処理の重い計算結果をメモ化することでレンダリング時のブロックを抑えること
    も出来る
    function Component ({a, b}) => {
    const resultA = useMemo(() => superDuperHighCostCalculation(a), [a]);
    const resultB = useMemo(() => superDuperHighCostCalculation(b), [b]);
    return <>
    {a}͔ΒʮΊͪΌͪ͘Όॏ͍ܭࢉʯΛͨ݁͠Ռ: {resultA}
    {b}͔ΒʮΊͪΌͪ͘Όॏ͍ܭࢉʯΛͨ݁͠Ռ: {resultB}
    >
    }
    #hatenaintern)*)+

    View full-size slide

  127. React Component 内で DOM にアクセスす

    • React に組み込まれている、参照を保持できる ref オブジェクトを作成する useRef を使う
    • ref オブジェクトは current プロパティに現在の値を持っている
    const textInput = useRef(null)
    const submit = (e) => {
    e.preventDefault()
    if (textInput.current.value.length < 100)
    return alert("101จࣈҎ্͕ඞཁͰ͢")
    createPost({ body: textInput.current.value })
    }
    return (



    )
    #hatenaintern)*)+

    View full-size slide

  128. DOM へのアクセスを避ける⽅が良い
    • DOM に直接アクセスすると、React の制御外のところで値が取得されたり変更されたりすることにな
    る。
    • ライブラリの都合などで本当に必要なときのみにしておくと良い
    const [text, setText] = useState("")
    const submit = (e) => {
    e.preventDefault()
    if (text < 100) return alert("101จࣈҎ্͕ඞཁͰ͢")
    createPost({ body: text })
    }
    return (

    setText(e.target.value)} />

    )
    #hatenaintern)*)+

    View full-size slide

  129. JavaScript をウェブアプリケーションで提供
    する際に使⽤するツールチェインについて
    TypeScript/JavaScript を実際のウェブアプリケーションでユーザ
    ーのウェブブラウザで実⾏する際には、いくつかのツールを組み
    合わせて変換したりしたものを提供する。
    #hatenaintern)*)+

    View full-size slide

  130. TypeScript のコードがユーザーに届くまでの例
    • TypeScript→JavaScript
    • tsc でも出来るが、babel で変換することも多い
    • JavaScript→ 対応ブラウザへの互換性がある JavaScript
    • API によってはサポートしているブラウザでそのままでは動かないことがあるので、babel を⽤いて、必要な polyfill などを組み⼊れる
    • TS→JS の変換も babel で⾏う場合は、それぞれ必要なプラグインを⼊れて実⾏
    • 個別の JavaScript ファイル → 単⼀の JavaScript ファイル
    • webpack などで JavaScript のファイルを統合(bundle)する。ES Modules を全ての環境でサポートしていれば不要という説もあるが、1 つ
    のファイルになっている⽅がパフォーマンスなどの観点で有利なこともある
    • JavaScript ファイル → 圧縮された JavaScript(+sourcemap)
    • ユーザーの⼿元に届くときには、容量を減らしたりするために minify©™されたコードにすることが多い。
    • そのままでは読むのが困難なので、開発者向けやエラートラッキングのために元の TS/JS との対応を記録したものが sourcemap
    !" 難読化とは異なり、変数名や関数名などを 1 ⽂字に置き換えるなどして容量の削減を図る。webpack に組み込まれている Terser では、TreeShaking という不要なコードの削除や不要な分
    岐の削除なども⾏われる。
    #hatenaintern)*)+

    View full-size slide

  131. webpack だと‧‧‧
    • TypeScript から JavaScript までの変換と互換性のための操作
    は babel(babel-loader 経由で利⽤)で⾏う
    • ファイルの結合などは webpack の主たる機能
    • 容量削減は Terser(webpack-terser-plugin 経由で利⽤)で⾏う
    #hatenaintern)*)+

    View full-size slide

  132. create-react-app について
    • React を使ったプロジェクトの作成、関連ツールの導⼊‧実⾏を⾃動化してくれる
    • 基本的にはまずはこれを使っておけば OK
    • webpack, babel, eslint など諸々の設定の⽣成も⾃動で⾏われます
    • npm start でローカル開発環境の⽴ち上げ、npm test でユニットテストが実⾏できる
    • 詳細は内部で使われているreact-scriptsに集約されている
    • create-react-app で利⽤するツールは定期的に⾒直されたりしていて、常に最新の React コミ
    ュニティの知⾒が活かされている
    • create-react-app をウォッチすることでそういった最新の動向というものにも触れられるの
    で、React の周辺について知りたい⼈はこのリポジトリを覗いてみるのがオススメ
    #hatenaintern)*)+

    View full-size slide

  133. JavaScript やフロントエンド周辺技術の標準
    (化)について
    主にブラウザ上で動く JavaScript や DOM、HTML、CSS などの API はそれぞれ
    以下のような仕様でそれぞれ標準化されている
    • ECMAScript
    • WHATWG HTML Living Standard
    • WHATWG DOM Living Standard
    • W9C CSS Specifications
    #hatenaintern)*)+

    View full-size slide

  134. なぜ仕様を知るのか
    • その API の振る舞いについて正しい振る舞いを定義しているのは仕様である。
    • 世の中に公開されている情報が数多くあるが、その情報の正しさを最終的に保
    証するための情報源が仕様である。
    • 例えば JavaScript や CSS などの振る舞いがウェブブラウザ間で異なる場合、
    その時に正しさを保証してくれるのは仕様である。
    • 実際、フロントエンドを中⼼に⾊んなことをしていると、仕様とブラウザの
    実装に差異があることに遭遇して、報告することがあります~。
    !" ウェブブラウザにバグ報告をするときにやること - ぱすたけ⽇記
    #hatenaintern)*)+

    View full-size slide

  135. ECMAScript について
    • JavaScript の標準仕様は ECMAScript という名前で、Ecma InternationalCDの中の Technical
    Committee DH(TCDH)という技術委員会が中⼼に策定されている。
    • 現在の仕様はhttps://github.com/tcDH/ecmacdcで管理されていて、 常に最新版が公開され
    続けている。
    • こういう常に最新版が公開されている形式を Living Standard と呼びます。
    • 毎年 6 ⽉頃のミーティングで ECMAScript cÑcÖ のようなタグが打たれて、バージョン番号が
    付与したものも公開されますが、その時点でのスナップショットであり、そのバージョン⾃
    体にはあまり意味はないですCC
    !! babel や tsc の設定で利⽤することもありますが、仕様としてはそんなに気にする必要はないです。このバージョンとは独⽴して、仕様の提案が進むタイミングでそれぞれの処理系におい
    て実装が⾏われて、利⽤可能になるからです。また、後述しますが polyfill などによって実⾏可能になることもあります。
    !" Ecma International は C#などの標準化作業も⾏っている
    #hatenaintern)*)+

    View full-size slide

  136. ECMAScript の Stage
    • ECMAScript には⾃由に提案(proposal)を出すことが出来る
    • Github 上で proposal が公開され、issue や PR や TCQR のミーティング
    などでの議論を経て、Stage が上がったりする
    • 責任者であるチャンピオンのステージを進めたいという意思も必要
    • 気になるプロポーザルがなかなか取り込まれない場合は、Issue やミーテ
    ィングノートを⾒るとヒントがあるかも
    • それらは次のようなステージを経て、Stage å になった後に ECMAScript の
    仕様に取り込まれる。
    #hatenaintern)*)+

    View full-size slide

  137. Stage の詳細
    ステージ ステージの概要
    ( アイデア 状態
    / 機能提案
    4 機能の仕様書ドラフトを作成した状態
    A 仕様としてはほぼ完成していて、ブラウザの実装やフィードバックを求め
    る段階
    Y 仕様策定が完了し、2 つ以上の実装YbYcが存在している状態
    ECMAScript · JavaScript Primer #jsprimer
    !" 主に Stage+ 以前時点での実装などはその後の仕様変更などの可能性もあるので、ブラウザの開発者向けフラグを有効にしているときだけ使えたり、prefix を付けた名前で API が提供され
    ることもある。それらも実装として許容されるなどの緩さはある。
    !" 2 つ以上の JavaScript のランタイムに実装が存在しているということが求められる。主なランタイムは Google Chrome や Node.js で使⽤されている V_ や Safari で使⽤されている
    JavaScriptCore、Firefox で使⽤されている SpiderMonkey、Facebook が開発している Hermes などがある。
    #hatenaintern)*)+

    View full-size slide

  138. ECMAScript の仕様と実装
    • Stage ( になったり、ECMAScript に取り込まれていなくても、ウェブブラウザなどに実装されて使⽤出来るようにな
    ることがある
    • 逆に実装されていないと、仕様に取り込めない
    • その状態で積極的に使⽤することでプロポーザルにフィードバックをすることができる
    • また、実装がない状態でもコミュニティや core-js によってできるまた polyfill 実装が提供されたり、babel による
    トランスパイルなどでアプリケーション内で使⽤できるようになることがある
    • それらを実⽤することでもプロポーザルにフィードバックができたり、有⽤性を⽰すことが出来る
    • ECMAScript のプロポーザルは常に全てが Open で、それに関わるディスカッションも Open なので、興味のある提案
    があったら、是⾮覗いてみて、使⽤し、ポジティブな点(úや問題点があれば是⾮フィードバックをすることで、未来の
    JavaScript 環境をよくすることに繋がります。
    !" ECMAScript のプロポーザルは多くの場合、その提案が「どのようなモチベーションがあるのか」、「どのような問題を解決するのか」、「どのようなユースケースがあるのか」などが記
    されているので、その有⽤性などを⽰すことも貢献に繋がります。
    #hatenaintern)*)+

    View full-size slide

  139. ウェブブラウザ上の JavaScript と
    ECMAScript
    • ウェブブラウザ上で実⾏できる JavaScript は ECMAScript の仕様に含まれているものだけではない
    • 例えば location.assign はWHATWG HTML Living Standard、document.querySelector はWHATWG DOM
    Living Standardで定義されている
    • WHATWG という組織^_によって更新‧管理されている HTML/DOM それぞれの Living Standard な仕様によ
    って管理されている。^k
    • ECMAScript の仕様ではないので、HTML や DOM を扱わない環境(Node.js など)では実⾏できない
    !" 以前は W(C によって HTML2、HTML2.5 などが策定されていたが、399 年 5 ⽉に WHATWG 側に歩み寄ることを表明、2021 年 1 ⽉ 29 ⽇には WHATWG が公開している Living Standard を
    正式に W(C の勧告とした。/参考:[https://future-architect.github.io/articles/vwv5wxv5a/ どうして HTML2 が廃⽌されたのか | フューチャー技術ブログ]
    !" 2004 年に Apple‧Mozilla‧Opera の 3 社によって設⽴された。その後、WEC とのコミュニケーションを続けながらもブラウザベンダーを取り込み、外堀を埋めながら HTML Living
    Standard を公開‧管理し続けていた
    #hatenaintern)*)+

    View full-size slide

  140. ウェブブラウザベンダと WHATWG 仕様
    • 主に Google Chrome 陣営は HTML や DOM に関わる API>?の提案を数多く⾏っている
    • これらは提案者である Google Chrome には取り込まれるが、Apple や Moziila の
    反対に会い、仕様としては取り込まれないことも多々ある
    • Chrome の仕様トラッカー: Chrome Platform Status
    • Mozilla の⽴場を表明しているウェブサイト: Mozilla Specification Positions
    • W}C 内の Web Incubator Community Groupというところで様々な提案が作成‧議
    論されている
    !" https://scrapbox.io/pastak-pub/⾯⽩ WebAPI<"" 連発 で⾊々紹介しています
    #hatenaintern)*)+

    View full-size slide

  141. W"C CSS Specifications
    • いわゆる CSS) と呼ばれる CSS の現在‧未来の仕様は
    WHATWG ではなく引き続き W)C によって更新‧管理‧策定が
    ⾏われている
    • All CSS specifications
    #hatenaintern)*)+

    View full-size slide