首頁 > web前端 > js教程 > 在 JavaScript 中實作 Ruby 的方法 Method

在 JavaScript 中實作 Ruby 的方法 Method

WBOY
發布: 2024-07-31 06:30:13
原創
1053 人瀏覽過

Implementing Ruby

突然覺得Ruby的methods方法是不是很方便呢?在編寫程式碼時,它會列出物件可用的所有方法和屬性,並允許您搜尋它們,這對於偵錯非常有用。

除此之外,它對於檢查 Rails 等框架特有的方法也很有效,有助於程式碼閱讀和理解函式庫。雖然參考官方文件或原始程式碼是一種很好的做法,但當您不需要深入研究或對方法名稱有模糊記憶時,methods 方法對於函式庫非常有幫助。

Ruby 的方法 Method

簡單介紹一下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 的繼承機制是由原型鏈支援的。

雖然並不總是顯而易見,但在引用某些屬性時,該過程涉及:

  1. 檢查接收者本身是否具有該屬性。
  2. 檢查父類別實例是否具有該屬性。
  3. 檢查父類別實例的父類別中是否存在該屬性。

此過程沿著鏈向上繼續,直到找到匹配項,然後將其返回。

find 方法的作用

鑑於上述情況,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 的說明就到此結束。

包起來

這總結了程式碼的解釋以及我所嘗試的內容。

這更多的是一個實驗性或有趣的練習,但由於它涉及一些知識和技術,我希望你發現它對你自己的應用程式有用或啟發。

以上是在 JavaScript 中實作 Ruby 的方法 Method的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板