」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 在 JavaScript 中實作 Ruby 的方法 Method

在 JavaScript 中實作 Ruby 的方法 Method

發佈於2024-08-21
瀏覽:632

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 的說明到此結束。

包起來

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

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

版本聲明 本文轉載於:https://dev.to/version1/implementing-rubys-methods-method-in-javascript-p1e?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 如何使用Python理解有效地創建字典?
    如何使用Python理解有效地創建字典?
    在python中,詞典綜合提供了一種生成新詞典的簡潔方法。儘管它們與列表綜合相似,但存在一些顯著差異。 與問題所暗示的不同,您無法為鑰匙創建字典理解。您必須明確指定鍵和值。 For example:d = {n: n**2 for n in range(5)}This creates a dict...
    程式設計 發佈於2025-07-03
  • Python中何時用"try"而非"if"檢測變量值?
    Python中何時用"try"而非"if"檢測變量值?
    使用“ try“ vs.” if”來測試python 在python中的變量值,在某些情況下,您可能需要在處理之前檢查變量是否具有值。在使用“如果”或“ try”構建體之間決定。 “ if” constructs result = function() 如果結果: 對於結果: ...
    程式設計 發佈於2025-07-03
  • 在GO中構造SQL查詢時,如何安全地加入文本和值?
    在GO中構造SQL查詢時,如何安全地加入文本和值?
    在go中構造文本sql查詢時,在go sql queries 中,在使用conting and contement和contement consem per時,尤其是在使用integer per當per當per時,per per per當per. [&​​​​&&&&&&&&&&&&&&&默元組方...
    程式設計 發佈於2025-07-03
  • 如何使用Depimal.parse()中的指數表示法中的數字?
    如何使用Depimal.parse()中的指數表示法中的數字?
    在嘗試使用Decimal.parse(“ 1.2345e-02”中的指數符號表示法表示的字符串時,您可能會遇到錯誤。這是因為默認解析方法無法識別指數符號。 成功解析這樣的字符串,您需要明確指定它代表浮點數。您可以使用numbersTyles.Float樣式進行此操作,如下所示:[&& && && ...
    程式設計 發佈於2025-07-03
  • MySQL中如何高效地根據兩個條件INSERT或UPDATE行?
    MySQL中如何高效地根據兩個條件INSERT或UPDATE行?
    在兩個條件下插入或更新或更新 solution:的答案在於mysql的插入中...在重複鍵更新語法上。如果不存在匹配行或更新現有行,則此功能強大的功能可以通過插入新行來進行有效的數據操作。如果違反了唯一的密鑰約束。 實現所需的行為,該表必須具有唯一的鍵定義(在這種情況下為'名稱'...
    程式設計 發佈於2025-07-03
  • 圖片在Chrome中為何仍有邊框? `border: none;`無效解決方案
    圖片在Chrome中為何仍有邊框? `border: none;`無效解決方案
    在chrome 在使用Chrome and IE9中的圖像時遇到的一個頻繁的問題是圍繞圖像的持續薄薄邊框,儘管指定了圖像,儘管指定了;和“邊境:無;”在CSS中。要解決此問題,請考慮以下方法: Chrome具有忽略“ border:none; none;”的已知錯誤,風格。要解決此問題,請使用以下...
    程式設計 發佈於2025-07-03
  • Go語言垃圾回收如何處理切片內存?
    Go語言垃圾回收如何處理切片內存?
    Garbage Collection in Go Slices: A Detailed AnalysisIn Go, a slice is a dynamic array that references an underlying array.使用切片時,了解垃圾收集行為至關重要,以避免潛在的內存洩...
    程式設計 發佈於2025-07-03
  • Java中如何使用觀察者模式實現自定義事件?
    Java中如何使用觀察者模式實現自定義事件?
    在Java 中創建自定義事件的自定義事件在許多編程場景中都是無關緊要的,使組件能夠基於特定的觸發器相互通信。本文旨在解決以下內容:問題語句我們如何在Java中實現自定義事件以促進基於特定事件的對象之間的交互,定義了管理訂閱者的類界面。 以下代碼片段演示瞭如何使用觀察者模式創建自定義事件: args...
    程式設計 發佈於2025-07-03
  • 如何從PHP中的Unicode字符串中有效地產生對URL友好的sl。
    如何從PHP中的Unicode字符串中有效地產生對URL友好的sl。
    為有效的slug生成首先,該函數用指定的分隔符替換所有非字母或數字字符。此步驟可確保slug遵守URL慣例。隨後,它採用ICONV函數將文本簡化為us-ascii兼容格式,從而允許更廣泛的字符集合兼容性。 接下來,該函數使用正則表達式刪除了不需要的字符,例如特殊字符和空格。此步驟可確保slug僅包...
    程式設計 發佈於2025-07-03
  • 如何在無序集合中為元組實現通用哈希功能?
    如何在無序集合中為元組實現通用哈希功能?
    在未訂購的集合中的元素要糾正此問題,一種方法是手動為特定元組類型定義哈希函數,例如: template template template 。 struct std :: hash { size_t operator()(std :: tuple const&tuple)const {...
    程式設計 發佈於2025-07-03
  • 如何使用Python有效地以相反順序讀取大型文件?
    如何使用Python有效地以相反順序讀取大型文件?
    在python 中,如果您使用一個大文件,並且需要從最後一行讀取其內容,則在第一行到第一行,Python的內置功能可能不合適。這是解決此任務的有效解決方案:反向行讀取器生成器 == ord('\ n'): 緩衝區=緩衝區[:-1] ...
    程式設計 發佈於2025-07-03
  • Python元類工作原理及類創建與定制
    Python元類工作原理及類創建與定制
    python中的metaclasses是什麼? Metaclasses負責在Python中創建類對象。就像類創建實例一樣,元類也創建類。他們提供了對類創建過程的控制層,允許自定義類行為和屬性。 在Python中理解類作為對象的概念,類是描述用於創建新實例或對象的藍圖的對象。這意味著類本身是使用...
    程式設計 發佈於2025-07-03
  • 如何使用PHP從XML文件中有效地檢索屬性值?
    如何使用PHP從XML文件中有效地檢索屬性值?
    從php $xml = simplexml_load_file($file); foreach ($xml->Var[0]->attributes() as $attributeName => $attributeValue) { echo $attributeName,...
    程式設計 發佈於2025-07-03
  • 為什麼我的CSS背景圖像出現?
    為什麼我的CSS背景圖像出現?
    故障排除:CSS背景圖像未出現 ,您的背景圖像儘管遵循教程說明,但您的背景圖像仍未加載。圖像和样式表位於相同的目錄中,但背景仍然是空白的白色帆布。 而不是不棄用的,您已經使用了CSS樣式: bockent {背景:封閉圖像文件名:背景圖:url(nickcage.jpg); 如果您的html,cs...
    程式設計 發佈於2025-07-03
  • 為什麼不````''{margin:0; }`始終刪除CSS中的最高邊距?
    為什麼不````''{margin:0; }`始終刪除CSS中的最高邊距?
    在CSS 問題:不正確的代碼: 全球範圍將所有餘量重置為零,如提供的代碼所建議的,可能會導致意外的副作用。解決特定的保證金問題是更建議的。 例如,在提供的示例中,將以下代碼添加到CSS中,將解決餘量問題: body H1 { 保證金頂:-40px; } 此方法更精確,避免了由全局保證金重置...
    程式設計 發佈於2025-07-03

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3