Code Fix

初級

TypeError: x is not a function の原因と直し方

関数ではない値を関数として呼び出そうとしたときに出るエラーです。変数名やメソッド名のタイプミス、あるいはプロパティと勘違いした呼び出しで頻発します。

エラーメッセージの読み方

main.js:3
main.js
ファイル名
3
行番号 — 実際にクラッシュした行
TypeError
例外クラス — 何が起きたか。ここを検索するのが最短です
total is not a function
内容 — 期待していたもの、または受け付けられなかったもの

このエラーが出る典型パターン

パターン1

 1  const total = 5;
 2  function getTotal() { return total; }
 3  console.log(total   ());
                    ^
main.js:3 console.log(total()); ^ TypeError: total is not a function

totalは数値であって関数ではありません。呼び出した結果を得たい場合は、値を返す関数(ここではgetTotal)を呼びます。

直し方: total を getTotal にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  const cart = { items: [] };
 2  cart.addItm    ("apple");
              ^
 3  console.log(cart.items.length);
main.js:2 cart.addItm("apple"); ^ TypeError: cart.addItm is not a function

cartにはaddItmという名前のメソッドは存在しません。配列に追加したい場合はcart.items.pushを呼びます。

直し方: addItm を items.push にします。

この問題を解いてみる →

パターン3

 1  const config = { name: "app", describe() { return this.name; } };
 2  console.log(config.getName ());
                           ^
main.js:2 console.log(config.getName()); ^ TypeError: config.getName is not a function

configにgetNameというメソッドは定義されていません。実際に定義されているdescribeを呼び出す必要があります。

直し方: getName を describe にします。

この問題を解いてみる →

パターン4

 1  const numbers = [3, 1, 2];
 2  numbers.short  ();
               ^
 3  console.log(numbers);
main.js:2 numbers.short(); ^ TypeError: numbers.short is not a function

配列を並び替えるメソッドはsortです。shortという名前のメソッドは存在しません。

直し方: short を sort にします。

この問題を解いてみる →

パターン5

 1  const str = "hello";
 2  console.log(str.toUpper    ());
                         ^
main.js:2 console.log(str.toUpper()); ^ TypeError: str.toUpper is not a function

他言語のtoUpper()の感覚で書くと起きます。JavaScriptで大文字化するメソッド名はtoUpperCaseです。

直し方: toUpper を toUpperCase にします。

この問題を解いてみる →

よくある誤解

ReferenceErrorと混同されがちですが別物です。変数やプロパティ自体は存在するのに、その中身が関数ではないときにTypeErrorになります。存在しない名前を参照したReferenceErrorとは原因が違います。

実務での勘所

この違いが起きる理由は、JavaScriptが「名前の解決」と「呼び出し」を別の2段階で行っているためです。obj.foo()を実行するとき、まずobj.fooという式を評価してその中身を取り出し(この時点ではfooという名前が存在しなくてもオブジェクトのプロパティ探索なのでundefinedという値になるだけで例外は起きません)、次にその取り出した値を実際に呼び出そうとします。取り出した値が関数でなければ、ここで初めてTypeErrorになります。一方、宣言されていない裸の識別子(foo()のようにドットが無い呼び出し)は、名前の解決自体がその場で失敗するためReferenceErrorになります。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)