🎉

【JavaScript】TypeError: ~ is not a function の原因と解決方法まとめ

に公開

はじめに

定義した関数 is not a function 

このエラーメッセージは何を意味し、どう解決するのか、実際に出会した問題とそれを解消してわかったことを簡単にまとめていきます。

前提

Emailアドレスを指定したチェックルールに基づいてチェックする関数を作成しました。
そのときに実装したコードが以下になります。

validation.js
const doesNotStartAtWithAt = email => email[0] != "@";
const doesNotHaveSpace = email => !/\s/.test(email);
const hasUppercaseAndLowercase = email => /[a-z]/.test(email) && /[A-Z]/.test(email);

function emailValidation(f, email){
    return f(email) ? "Email is correct." : "Email is not correct.";
}

module.exports = { doesNotStartAtWithAt, doesNotHaveSpace, hasUppercaseAndLowercase, emailValidation }; 
validationTest.js
const { doesNotStartAtWithAt, doesNotHaveSpace, hasUppercaseAndLowercase, emailValidation } = require('../src/validation.js');

const tests = {
    "case1" : {
        "input" : {
            "validator" : doesNotStartAtWithAt,
            "email" : "@gmail.com"
        },
        "output" : "Email is not correct."
    }, 
    "case2" : {
        "input" : {
            "validator" : doesNotStartAtWithAt,
            "email" : "kkk@gmail.com"
        },
        "output" : "Email is correct."
    },
    "case3" : {
        "input" : {
            "validator" : doesNotHaveSpace,
            "email" : "Hello world"
        },
        "output" : "Email is not correct."
    },
    "case4" : {
        "input" : {
            "validator" : doesNotHaveSpace,
            "email" : "Helloworld"
        },
        "output" : "Email is correct."
    },
    "case5" : {
        "input" : {
            "validator" : hasUppercaseAndLowercase,
            "email" : "hello world"
        },
        "output" : "Email is not correct."
    },
    "case6" : {
        "input" : {
            "validator" : hasUppercaseAndLowercase,
            "email" : "HELLO WORLD"
        },
        "output" : "Email is not correct."
    },
    "case7" : {
        "input" : {
            "validator" : hasUppercaseAndLowercase,
            "email" : "Hello world"
        },
        "output" : "Email is correct."
    },
    "case8" : {
        "input" : {
            "validator" : hasUppercaseAndLowercase,
            "email" : ""
        },
        "output" : "Email is not correct."
    }
}

for(const [key, test] of Object.entries(tests)){
    const { validator, email } = test.input;
    const output = emailValidation(validator(email));
    const expected = test.output;
    const result = (output === expected) ? "Success" : "Failure";

    console.log(`Test ${key}: ${result}`);
}

エラーメッセージ

node validationTest.js
/Users/mavo/project/algorithm-solutions/HigherOrderFunc/problems/02_validation/js/src/validation.js:6
    return f(email) ? "Email is correct." : "Email is not correct.";
           ^

TypeError: f is not a function
    at emailValidation (/Users/mavo/project/algorithm-solutions/HigherOrderFunc/problems/02_validation/js/src/validation.js:6:12)
    at Object.<anonymous> (/Users/mavo/project/algorithm-solutions/HigherOrderFunc/problems/02_validation/js/tests/validationTest.js:64:20)
    at Module._compile (node:internal/modules/cjs/loader:1369:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
    at Module.load (node:internal/modules/cjs/loader:1206:32)
    at Module._load (node:internal/modules/cjs/loader:1022:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
    at node:internal/main/run_main_module:28:49

Node.js v20.12.2

エラーメッセージの意味

TypeError: f is not a function

ここからわかること

  • 値の型が期待される型と一致しない
  • fは関数ではない

関数でないものを、関数呼び出ししようとした際に発生するエラーです。また適切な関数が定義されていることを期待されているが、定義されていない場合も発生します。
関数名のタイプミスをしていないか確認してみましょう。また、呼び出そうとしてるオブジェクトがそのメソッドを持っているかどうかも確認してみてください。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Errors/Not_a_function より引用

エラーメッセージから導ける仮説

  • 関数名のタイプミス
  • 呼び出しているものが関数ではない
  • メソッドが存在しない(今回のケースではオブジェクトは使用していないので除外)

原因

関数への引数の渡し方に問題があり、関数の要件を満たしていなかったこと

問題の箇所
const output = emailValidation(validator(email));

emailValidation() は関数と文字列を引数にとりますが、validator()の引数に文字列を入れた結果を格納してしまっていました。

解決策

emailValidation()に関数と文字列を渡す

改善前
const output = emailValidation(validator(email));
改善後
const output = emailValidation(validator, email);

まとめ

今回は、~ is not a function というエラーメッセージの解決法の一部を実体験を基に紹介させていただきました。

JavaScriptでは、function() のように括弧 () を付けて呼び出すと、JavaScriptエンジンはそれが関数であると期待します。
しかし、呼び出そうとした対象( ~ の部分)が、実際には関数ではなく、文字列、オブジェクト、undefinedなどだった場合に、このエラーが発生するようです。

今回のケースでは、関数を呼び出したつもりが、引数が定義した関数の引数ではなかったためにエラーが発生していました。
この他にも、タイプミスや予期しない型だったりとエラーの要因が状況によって変わりますので、まずはメッセージを丁寧に読んでいき、仮説から検証していきましょう!

最後までお読みいただき、ありがとうございました。

参考URL

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Errors/Not_a_function

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/TypeError

Discussion