はじめに
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)
このobj
をProxyでラップすることで、メソッドを呼び出すことができるようにします
プログラムソース
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