突然ですが、Rubyのメソッドメソッドって便利じゃないですか?コードを記述するときに、オブジェクトで使用できるすべてのメソッドとプロパティがリストされ、それらを検索できるため、デバッグに非常に役立ちます。
それに加えて、Rails のようなフレームワークに固有のメソッドをチェックするのにも効果的で、コードの読み取りとライブラリの理解に役立ちます。公式ドキュメントやソース コードを参照することをお勧めしますが、メソッド メソッドは、深く調べる必要がないライブラリやメソッド名の記憶が曖昧な場合に非常に役立ちます。
Ruby のメソッドメソッドを簡単に紹介すると、次のようになります。
オブジェクト#メソッド
obj の public メソッドと protected メソッドの名前のリストを返します。これには、obj の先祖でアクセスできるすべてのメソッドが含まれます。オプションのパラメーターが false の場合、obj のパブリックおよび保護されたシングルトン メソッドの配列が返されます。配列には、obj に含まれるモジュールのメソッドは含まれません。
言い換えると、受信側からアクセスできるプロパティとメソッドの配列オブジェクトを返します。
このメソッドは、Object を継承するすべてのクラスの祖先である Object クラスに実装されているため、Object を継承する任意のクラスで使用できます。
サンプルコード
class Hoge attr_accessor :fuga def bar puts '' end end puts Hoge.new.methods // => [:bar, :fuga=, :fuga, :hash, :singleton_class, :dup, ...] puts Hoge.new.grep /fuga/ // => [:fuga=, :fuga]
例に示すように、Array オブジェクトが返されるため、grep メソッドを使用してメソッドのリストを検索することもでき、非常に便利です。
そこで、これを JS で実現できないかと考え、試してみました。
以下は実際のコードです。
クラス名は任意ですが、ここでは PropertyFinder という名前にします。
class PropertyFinder { constructor(receiver) { this.receiver = receiver } grep(regexp, options = {}) { let res = [] if (typeof regexp === 'string') { return this.find((name) => name.includes(regexp)) } if (regexp instanceof RegExp) { return this.find((name) => regexp.test(name)) } return [] } toString() { return this.find(() => true) } find(detect) { const list = Object.getOwnPropertyNames(this.receiver).filter(it => detect(it)) if (!this.receiver.__proto__) { return list } const ancestors = new PropertyFinder(this.receiver.__proto__).find(detect) return [...list, ...ancestors] } }
コードについては後ほど説明しますが、まずは使い方から始めましょう。
クラスを定義したら、次のようにオブジェクト クラスのプロパティにメソッドを追加できます。
Object.prototype.methods = function () { return new PropertyFinder(this) }
こうすることで、Objectを継承したクラスのインスタンスに対してmethodsメソッドを使用できるようになります。ただし、以下の注意事項をご理解の上、ご自身の責任でご使用ください。
実行例をいくつか示します:
class Hoge { fuga() { console.log('fuga') } } console.log(new Object().methods().toString()) // => ['constructor', 'constructor', '__defineGetter__', '__defineSetter__', 'hasOwnProperty' ...] console.log([].methods().toString()) // => ['length', 'length', 'constructor', 'at', 'concat', ...] console.log(new Hoge().methods().grep(/fuga/) // => ['fuga']
*このコードは運用環境での使用は推奨されません *
モンキーパッチを介して上位クラスにプロパティを追加することはアンチパターンであり、JS 仕様の将来の変更で問題が発生する可能性があります。ご自身の責任において慎重に使用してください。
参考: モンキーパッチングの短所
それでは、コードの説明に移りましょう。
PropertyFinder で最も重要なメソッドは find メソッドです。このメソッドは、指定されたオブジェクトのプロトタイプ チェーンを走査し、アクセス可能なプロパティを検索し、それらをリストとして返します。
toString メソッドと grep メソッドは find を使用するだけなので、これ以上の説明は必要ありません。
プロトタイプ チェーンに馴染みのない人もいるかもしれませんが、これは Object クラスからのプロパティの継承です。
継承とプロトタイプチェーン | MDN
詳細は MDN ドキュメントで説明されていますが、JavaScript の継承メカニズムはプロトタイプ チェーンによってサポートされています。
必ずしも明らかではありませんが、プロパティを参照する場合、そのプロセスには次のことが含まれます。
このプロセスは、一致するものが見つかるまでチェーンを上っていき、一致したものが返されます。
上記を考慮すると、PropertyFinder の find メソッドはこのメカニズムを実装しており、__proto__ を再帰的に探索することでプロパティのリストを取得できます。
これは、__proto__ を再帰的に探索してリストを取得することでこれを実現する実装です:
find(detect) { const list = Object.getOwnPropertyNames(this.receiver).filter(it => detect(it)) if (!this.receiver.__proto__) { return list } const ancestors = new PropertyFinder(this.receiver.__proto__).find(detect) return [...list, ...ancestors] }
PropertyFinder の説明は以上です。
コードの説明と私が試したことは以上です。
これは実験的または遊び心のある演習でしたが、いくつかの知識とテクニックが含まれていたため、ご自身のアプリケーションに役立つ、またはインスピレーションを感じていただければ幸いです。
以上がRuby のメソッドを実装する JavaScript でのメソッドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。