入門のファイルを直接書き換えてしまう
途中で分からなくなったときに戻る先が無くなります。script.js はそのまま残し、コピーを app.js として作ってください
レッスンの本文で注意している点を、つまずきの側から53件ぶん並べ直しました。書いた覚えのある形が見つかったら、 そのままレッスンに戻って前後を読めます。
途中で分からなくなったときに戻る先が無くなります。script.js はそのまま残し、コピーを app.js として作ってください
下のように配列の宣言と描画が同じ関数に入っていると、データを外から取ってくる形に変えるときに関数ごと書き直しになります。次のレッスンからの主題がここです
このコースで育てるもので詳しく読む非同期処理はこのコースの目玉ですが、try と catch を知らないまま await のエラー処理に入ると、例外の話をしているのか非同期の話をしているのか切り分けられなくなります。第6章を先に置いてあるのはそのためです
下の書きかたは、ただの文字列を評価しただけで終わります。"use strict"; の前に文を置けるのはコメントだけです
use strict; と書くと、use という変数を参照する式になります。strict mode ならこれ自体が ReferenceError になりますが、まだ有効になっていないので何も起きません
strict mode にした直後は、それまで隠れていた不具合が一気に表に出ます。増えたのはエラーであって不具合ではありません。1 つずつ潰すほうが、黙って間違った値が表示され続ける状態よりも短時間で終わります
strict mode が先に教えてくれる間違いで詳しく読む1 行でも document が出てきたら、それはもう変換関数ではありません。戻り値だけで確かめられなくなります
tags を持たない作品が 1 件でもあると、そこで処理全体が止まります。第9章で API から取ってきたデータには、項目が欠けている行が混ざります
変換のついでに work 自体へ項目を足すと、元の配列が汚れます。新しいオブジェクトを作って返してください
stats: { views } は「開く指示」であって変数宣言ではありません。親も使うなら { stats, stats: { views } } と両方書きます。
キー、変数名、既定値の順です。既定値は必ずいちばん後ろに置きます。
分割代入で必要な値だけ取り出すで詳しく読む引数全体には = {} があるのに、stats には付いていません。引数は渡されているので外側の既定値は使われず、undefined の stats を開いて落ちます。開く階層それぞれに受け皿が要ります。
まとめる対象が「残り」である以上、後ろに何かを置くことはできません。
スプレッドとレストで組み替えるで詳しく読むmerged.tags は defaults.tags と同じ配列を指しています。tags: [...merged.tags, "HTML"] のように、新しい配列を作って差し替えてください。
keys はオブジェクトのメソッドではなく Object に生えた関数です。配列の arr.map() とは呼びかたが違います。
fromEntries が受け取れるのは [キー, 値] の 2 要素配列の並びです。[title, count] の形で返してください。
キーが必要になる可能性があるなら、最初から entries で開きます。values は合計や最大値のように、キーを完全に捨ててよいときだけ使います。
+ で立てる3 + 2 は 5 になり、注目が降りて新着が立ったことになります。3 | 2 なら 3 のままです。
^ を使う^ は切り替えです。今の状態に関係なく降ろしたいなら & ~ を使います。
&& と & を書き間違える1 文字違いで、常に真になる条件ができあがります。フラグを扱っているファイルでは特に見落としやすいので、書いたあとに読み返してください。
ビット演算でフラグをまとめるで詳しく読むオブジェクトリテラルの感覚でカンマを打つと構文エラーになります。クラスの本体はカンマで区切りません。
クラスとインスタンスで詳しく読むthis を書き忘れるtitle とだけ書くと、インスタンスのプロパティではなく変数を探しに行きます。見つからなければ ReferenceError です。
constructor で値を返そうとするreturn { title } のようにオブジェクトを返すと、new の結果がそのオブジェクトに差し替わり、メソッドを持たない素のオブジェクトができます。constructor では this に代入するだけにします。
# フィールドを宣言せずに使うconstructor の中でいきなり this.#views = 0 と書いても、クラスの直下に宣言が無ければ動きません。
set の中で同じ名前に代入するset views(value) の中で this.views = value と書くと、また set views が呼ばれます。それが延々と続いてスタックがあふれます。代入先は必ず #views のほうです。
get にかっこを付けて呼ぶwork.views() と書くと、返ってきた数値を関数として呼ぼうとして TypeError になります。アクセサはかっこなしで使います。
super() を呼ばないextends を書いたら、子の constructor では必ず super() を呼びます。呼ばないまま constructor が終わっても ReferenceError です。
super() を引数なしで呼ぶと、親の constructor の引数が全部 undefined になります。エラーにはならないので、undefined (undefined) という文字が画面に出てから気づくことになります。
super.describe() を this.describe() と書く上書きしたメソッドの中で this.describe() を呼ぶと、上書きしたほう自身がもう一度呼ばれます。止まらなくなって RangeError になります。親を呼ぶときは super. です。
static を呼ぶwork.from(record) と書くと TypeError です。static はクラスに付いているので Work.from(record) と書きます。
static のメソッドの中で this をインスタンスのつもりで使うstatic の this はクラス自身です。this.title と書いても undefined にしかなりません。
format を fomat と書いても、その場ではエラーになりません。子のインスタンスで format() を呼ぶと親の format が静かに動き、「人気」が付かない行が混ざります。上書きが効いていないときは、まず名前を見比べます。
#works を返してしまうget works() { return this.#works; } と書くと、隠した意味がありません。返した配列は同じ入れ物なので、外から push も splice も通ります。渡すなら [...this.#works] のようにコピーを返します。
totalViews を全件で計算するthis.#works.reduce(...) と書くと、非公開の作品の表示回数まで合計に入ります。合計と件数で、数える対象を揃えます。
limit に何も渡さないtopTitles() のように引数なしで呼ぶと slice(0, undefined) になり、全件が返ります。0 件のつもりで呼ぶと全部出てくるので、呼ぶ側で件数を決めて必ず渡します。
失敗しうるのは JSON.parse のほうなので、囲む場所がずれている。try には失敗しうる行を入れる。ただし囲みすぎもよくない。関係のない処理まで入れると、どこで失敗したのか catch から分からなくなる。
これで画面は止まらなくなるが、なぜ何も出ないのかが誰にも分からなくなる。この章の最後の回で、受け取った失敗を利用者に見える形で出す。
try catch finallyで詳しく読むメッセージは環境で変わるので、この if はいつか静かに通らなくなる。分けたいときは error.name を見るか、次のレッスンで作る自前のエラークラスを使う。
これは "ValidationError" ではなく "Error" と出る。name は継承元の値がそのまま残るので、自分で入れる。
これは実行した時点で ReferenceError になる。継承したクラスでは super() を呼ぶまで this を触れない。super を必ず先頭に置く。
console.log は処理を止めないので、その下の行がそのまま動く。止めたいなら throw を書く。
自分でエラーを投げるで詳しく読むこれは成功したときに is-error を外していない。一度失敗すると、そのあと何回成功しても赤い枠が残る。try に入る前に clearError() を呼ぶ。
alert は押すまで消えず、押したら跡が残らない。利用者は文言を読み返せず、画面のどこが失敗したのかも分からない。失敗した場所の近くに、消えない形で出す。
失敗を画面に出すで詳しく読むこれで見えなくはなるが、次に失敗したときに出す先が無くなる。隠すのと消すのは違う。付け外しするのは class だけにする。
失敗を画面に出すで詳しく読むnull を忘れる当たらなかったときに null が返ることを忘れると、その場では動いて後で落ちます。
. をそのまま書く正規表現の . は「どれか 1 文字」です。ピリオドそのものを探したいときはバックスラッシュを付けます。
{4} を「4 桁ちょうど」だと思い込む/\d{4}/ は「4 個並んだ箇所がある」という意味であって、「全体が 4 桁」ではありません。"12345" にも当たります。全体を縛りたいときは、次のレッスンで扱う ^ と $ が要ります。
g フラグを付けた正規表現を test で使い回すこれは知らないと必ず一度は踏みます。g フラグ付きの正規表現オブジェクトは lastIndex という「次にどこから探すか」を内部に持っていて、test が当たるたびにそれを進めます。関数の外に置いて使い回すと、2 回目の呼び出しが前回の続きから探し始めて false になります。
^ と $ を付け忘れる付け忘れると、途中に混ざっていれば通る判定になります。
入力を検証するで詳しく読む+ は 1 個以上なので空文字列は弾けますが、* は 0 個以上なので通します。空の入力を弾くつもりで * を書くと素通りします。
replace は元の文字列を書き換えません。呼びっぱなしにすると何も変わりません。
g を付け忘れて 1 件だけ置き換わるテストケースが 1 件しか日付を含まないと気付けません。複数入った文字列で必ず確かめます。
置換とキャプチャで詳しく読む第 1 引数は当たった全体で、キャプチャは第 2 引数からです。ここを 1 つずらすと、年のつもりで 2026-04-01 全体を受け取ってしまいます。