0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptで存在しない関数を呼び出した場合、エラーにせずに何らかの処理を実行する

Last updated at Posted at 2024-06-03

はじめに

PHPのマジックメソッドやRubyのmethod_missingに近い機能をJavaScriptで実装する方法です

通常、javascriptでは、存在しない関数を呼び出すとエラーが発生します

test.js
const obj = {};
obj.some_method();
$ node test.js
E:\Users\tkykn\git\proxy\js_method_missing\test.js:2
obj.some_method();
    ^

TypeError: obj.some_method is not a function
    at Object.<anonymous> (E:\Users\tkykn\git\proxy\js_method_missing\test.js:2:5)

このobjProxyでラップすることで、メソッドを呼び出すことができるようにします

プログラムソース

method_missing.js
/**
 * 【javaScriptで存在しない関数を呼び出した場合、エラーにせずに何らかの処理を実行する】
 *   --- PHPのマジックメソッドやRubyのmethod_missingに近い機能をJavaScriptで ---
 *
 * javascriptでは、存在しない関数を呼び出すとエラーが発生してしまうが、
 * Proxyを使うことで、存在しないプロパティーアクセスや関数呼び出しのエラーを回避することができる
 *
 * ①存在しないプロパティーにアクセスがあった場合「Proxyのget()ハンドラー」で何もしない関数を返す
 *  ⇒関数呼び出しでのエラー回避と
 * ②何もしない関数もProxyでラップしておく。関数呼び出し時、apply()が呼び出されるので任意の処理をお個々なうことができる
 */
const target = { hoge: 'taget.hoge', bar: () => 'target.bar' };

const proxy = new Proxy(target, {
  get(target, name, receiver) {
    console.log(`get property ${name}`);
    if (name in target) {
      // オブジェクトに存在するプロパティーは値をそのまま返す
      return target[name];
    } else {
      // 存在しないプロパティーにアクセスがあった場合temp_func(空の関数)を返す
      //  ⇒ 呼び出し元では、指定した関数が定義されているように見える
      const temp_func = () => {};
      // Proxyでラップして返すことで、temp_func関数呼び出し時にapplyフックが実行される(割り込む)
      const func_proxy = new Proxy(temp_func, {
        apply(target, thisValue, args) {
          // 関数名と引数を表示する(nameはプロパティーアクセス時のキー名)
          console.log(`call missing function ${name}(${args})`);
          // return target.apply(thisValue, args); // 関数を呼び出すならこのように記載する
          return name; // 任意の処理を行い結果を返す(ここでは呼び出された関数名を返している)
        },
      });
      target[name] = func_proxy;
      return target[name];
    }
  },
});

// targetに存在するプロパティーを呼び出した場合は、apply()が実行されない(元の関数が呼ばれる)
console.log(proxy.hoge);
console.log(proxy.bar());

// targetに存在するプロパティーを呼び出した場合、temp_funcが返される
// temp_func()を関数として呼び出すと、proxyのapply()が呼び出されるので任意の処理を行うことができる
console.log(proxy.callFunc(12, 'ab'));
console.log(proxy.findById(12345));
  • 実行結果
    • 存在しない関数(callFunc())が呼び出され、引数が表示されている
    • 戻り値として、関数名が帰ってきている
$ node method_missing.js
~~ 一部省略 ~~
get property callFunc                  ・・・存在しないプロパティーにアクセス⇒temp_funcが返される
call missing function callFunc(12,ab)  ・・・temp_func()を呼び出した結果、apply()が割り込み、ログを出力している
callFunc
get property findById
call missing function findById(12345)
findById
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?