突然覺得Ruby的methods方法是不是很方便呢?編寫程式碼時,它會列出物件可用的所有方法和屬性,並允許您搜尋它們,這對於偵錯非常有用。
除此之外,它對於檢查 Rails 等框架特有的方法也很有效,有助於程式碼閱讀和理解函式庫。雖然參考官方文件或原始程式碼是一種很好的做法,但當您不需要深入研究或對方法名稱有模糊記憶時,methods 方法對於函式庫非常有幫助。
簡單介紹Ruby的methods方法,長這樣:
物件#方法
傳回 obj 的公共方法和受保護方法的名稱清單。這將包括 obj 祖先中可訪問的所有方法。如果選用參數為 false,則傳回 obj 的公共和受保護單例方法的數組,則該數組將不包含 obj 中包含的模組中的方法。
換句話說,它傳回一個包含可從接收者存取的屬性和方法的陣列物件。
該方法在Object類別中實現,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 類別的屬性新增方法,如下所示:
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 的說明到此結束。
這總結了程式碼的解釋以及我所嘗試的內容。
這更多的是一個實驗性或有趣的練習,但由於它涉及一些知識和技術,我希望您發現它對您自己的應用程序有用或啟發。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3