実用性は置いといて、JavaScriptのProxy
で、こんなことできるかなと思ってやってみたもの。
const recorder = new Proxy(() => [], {
apply: function (target, _thisArg, args) {
return [...target(), ...args];
},
get: function (target, prop) {
return new Proxy(() => [...target(), prop], this);
},
});
// アクセスしたプロパティを記録していき、関数として呼ぶと配列を吐く
console.log(
recorder.hoge.fuga.piyo.hogehoge.hogefuga.hogepiyo.foo.bar.baz.foober.barbaz.foobarbaz[1][2][3]()
);
// ファイルパスを作るとか?
console.log({
path: recorder['C:\\'].Users.Public.Downloads('somefile.txt').join('\\'),
});
// 丸サ進行
console.log({ chords: recorder.FMaj7.E7.Am7.Gm7.C7() });
動かしてみる
型をつける
- 一応型をつけました。
- もうちょっとスマートな書き方がありそうな気がします。
- できれば
as
を撲滅したい。
- できれば
- もうちょっとスマートな書き方がありそうな気がします。
interface CallableProperty {
(...args: string[]): string[];
[key: string]: CallableProperty;
}
const recorder = new Proxy<CallableProperty>(
((...args: string[]) => args) as CallableProperty,
{
apply: function (target, _thisArg, args) {
return [...target(), ...args];
},
get: function (target, prop) {
return new Proxy(() => [...target(), prop], this);
},
}
);
終わりに
- いつかライブラリを作ったりすることがあれば役に立つことがあるかもしれない。
-
Proxy
はいろいろ悪さできて楽しそうですね。-
Vueはこれを使ってリアクティブな値を実現しています。
- これを知らなかったので、以前ハマったことがあるのですが、それはまた別のお話。
-
Vueはこれを使ってリアクティブな値を実現しています。