はじめに
この記事は、2024年上期に自主制作から学んだことおよび自己研鑽として取り組んだことをまとめた記事です。
自主制作から学んだこと
自主制作以外については記事を執筆することで学んだことをアウトプットしていますが、自主制作で学んだことはアウトプットできていないのでこちらの記事でアウトプットします。
型の理解が深まった
一番の収穫は型の重要性を(ようやく)理解できたことです。
HTMLElementのインスタンスかどうかで型を絞ろう
今までnullチェックを兼ねた早期リターンは今まで以下のようにしていたのですが、
const element = document.querySelector("[data-sample]");
if(!element) return;
今回レビューいただいた方から以下のようにHTMLElementのインスタンスかどうかで判定した方が良い、と言うことを教えていただきました。
const element = document.querySelector("[data-sample]");
if(!(element instanceof HTMLElement)) return;
上記のようにHTMLElementでチェックすることで、element
が持っているメソッドをコードエディターが自動で判定して予測として提示してくれるようになります!!!
例えば、button
要素を取得した場合は、以下のようにHTMLButtonElementのインスタンスかどうかを判定します。
const buttonElement = document.querySelector("[data-button-sample]");
if(!(buttonElement instanceof HTMLButtonElement)) return;
上記の記述をすることで、HTMLButtonElementのインスタンスメソッドであるdisabled
が予測変換に出てくるのです!!!とっても便利!!!
HTMLElementのインスタンスメソッドかどうかの判定だとdisabled
は予測変換に出てきません><
元々属性を取得する時はgetAttribute
を利用することが多かったのですが、上記のように型を絞った上で予測変換を利用した方がタイポを防げる、というメリットもあります。
nullチェックの要否は機械的に判定しよう
自主制作で以下のようなコードを書いていました。
この時自分は、elements
はdata-sample
属性を持っている要素を配列風オブジェクトにしているので、forEachで取り出しているelement
は必ずdata-sample
属性を持っており、valueは何かしらの値か空文字が格納されるため、nullチェックは不要だと考えていました。
const dataSampleKey = 'data-sample';
const elements = document.querySelectorAll(`[${dataSampleKey}]`);
elements.forEach((element) => {
const value = element.getAttribute(dataSampleKey);
const target = document.getElementById(value);
console.log(target);
})
しかし、「ここは必ずstringが入ってくるだろう」と判断できるのは人間だけとのことで、「実際何が入ってくるか」よりは「前後関係はさておきこの変数に格納される可能性がある型は機械的に考えるとstringもしくはnullになる」ので、nullチェックをした方が良い、と言う考え方を学びました。
実際、TypeScriptのエラー判定が出るような設定をしたところ「stringかnullが入ってくるよ」というエラー判定が出ます。
上記のサンプルコードでnullチェックを行う場合は該当行にNull 合体演算子 (??)を利用すると良い、ということも学びました!
const target = document.getElementById(value ?? "");
JavaScriptで生成した要素を追加するときはDocumentFragmentを使おう
選択した都道府県に応じて都道府県の選択肢を変更する実装を行いました。
当初、「大阪」「京都」のようなinput要素を直接DOMに追加する実装を行なっていたのですが、選択肢の回数分Documentを直接操作するのはパフォーマンス的に良くない、ということでDocumentFragmentの存在を教えていただきました。
こうすることで、以下のようにDocumentFragmentを追加するときにだけDocumentを操作するので、DOMへのアクセスを1回だけに減らすことができます。
- 「大阪」のインプット要素を作成
- DocumentFragmentに追加
- 上記を都道府県の個数分繰り返す
- DocumentFragmentをDocumentに追加
パフォーマンス観点で優れているのでdocumentに要素を追加する場合は積極的に使っていきたいと思います!
その他こまごました学び
ARIA ライブリージョンは基本polite
を使おう
上記に記載の通り、ユーザの操作に応じて選択肢など表示が変わることから、aria-live
属性を利用してユーザに通知が届くような実装をしていました。
このときaria-live="assertive"
を設定していたのですが、ARIA ライブリージョン(MDN)にも以下のように記載がある通り、aria-live="assertive"は緊急性の高い通知にのみ使用すべきで、通常はaria-live="polite"を使った方が良い、ということを学びました。
通常、aria-live="polite" のみが使われます。(中略)スクリーンリーダーはユーザーがアイドル状態になったときに読み上げを行います。
aria-live="assertive" は、即時に伝えてユーザーの注意を引く必要のある、時間にシビアな通知にのみ使用します。一般的に assertive なライブリージョンへの変更は、スクリーンリーダーがその時に読み上げているものに割り込みます。
data
属性の属性名と値を変数名にするときはkey
とvalue
がおすすめ
いつも変数名をどうしたらいいのか悩んでしまうのですが、data
属性は「key」と「value」の関係になっているとのことで、それぞれ変数に格納したい場合は以下のようにするのもおすすめです。
const dataSampleKey = 'data-sample-key';
const dataSampleValue = document.querySelector(`[${dataSampleKey}]`).getAttribute(dataSampleKey);
まとめ
今回、JavaScriptの品質向上を目的に自主制作を行いました。
社内の経験豊富なメンバーにレビューいただいたこともあり、自分が考慮できていなかった点やワンランク上の実装の仕方を学ぶことができました。
型の重要性を理解したことで、TypeScriptを学ぶことへのハードルがかなり下がったと感じています。
また、案件対応時に困っているメンバーをフォローできるようになったり、コードレビューでより品質が高い書き方を提案できたりと、チーム全体の品質向上に寄与できたと思います。
以下は自主制作始め、当初取り組む予定だったものをそれぞれの取り組み状況を載せています。
期初の目標と取り組み状況
期初の目標
2023年の自己研鑽を踏まえ、この半期では以下に取り組むこととしました。
なお、優先順位を考慮しMUSTを太文字としています。
- インターネット関連
- HTTPとは
- ドメインネームとは
- ホスティングとは
- DNSとは
- HTML
- アクセシビリティ (2023年下期から後ろ倒し)
- パフォーマンス
- CSS
- コンテンツモデルについて
- コードレビュー力向上 (2023年下期から継続)
- Javascript
- DOMとは
- ECMA Scriptの仕様周り(2023年下期から継続)
2024年9月時点での取り組み状況
MUSTの項目について、インプットとアウトプットをそれぞれ以下の通り取り組んでいます。
-
アクセシビリティ
-
インプット
- ウェブ開発を学ぶ > アクセシビリティを読む
- WCAG 2.2を読む
- アウトプット
-
インプット
-
パフォーマンス
- インプット
-
アウトプット
- 記事執筆&公開
-
JavaScript DOM操作周り
- インプット
-
アウトプット(自主制作)
-
成果物:https://improve-quality.web.app/
- API通信の実装
- 画像遅延ロード&無限スクロール
-
レビュー中:https://improve-quality--pr18-feat-localstrage-jtciq74d.web.app/
- LocalStorage機能
-
成果物:https://improve-quality.web.app/
MUSTを優先で取り組んだため、WANT項目については現時点で全く取り組めていません。
2024年下期に取り組みたいこと
細かいところはまだ全く考えられていませんが、下期にはTypeScriptにチャレンジしようかなと思っています。
また学んだことを社内外に共有できるようがんばります!
参考
過去の取り組みはこちらです。
https://qiita.com/msuzuna/items/39009934edd7cb35e3ec