«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Реализация методов Ruby в JavaScript

Реализация методов Ruby в JavaScript

Опубликовано 21 августа 2024 г.
Просматривать:532

Implementing Ruby

Внезапно, разве метод Ruby не удобен? При написании кода он перечисляет все методы и свойства, доступные для объекта, и позволяет осуществлять поиск по ним, что очень полезно при отладке.

Кроме того, он также эффективен для проверки методов, специфичных для таких фреймворков, как Rails, помогая читать код и понимать библиотеки. Хотя хорошей практикой является обращение к официальной документации или исходному коду, метод методы весьма полезен для библиотек, в которых вам не нужно глубоко погружаться или когда у вас смутные воспоминания об именах методов.

Методы Ruby Метод

Если кратко представить метод методов Ruby, он выглядит так:

Объект#метод

Возвращает список имен общедоступных и защищенных методов объекта. Сюда будут включены все методы, доступные в предках 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 следующим образом:

Object.prototype.methods = function () {
    return new PropertyFinder(this)
}

Сделав это, вы сможете использовать метод методов для экземпляров классов, наследуемых от Object. Однако обратите внимание на предостережение ниже и используйте его на свой страх и риск.

Вот несколько примеров выполнения:

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, но механизм наследования JavaScript поддерживается цепочкой прототипов.

Хотя это не всегда очевидно, при упоминании какого-либо свойства процесс включает в себя:

  1. Проверка наличия свойства у самого получателя.
  2. Проверка наличия свойства у экземпляра родительского класса.
  3. Проверка существования свойства в родительском классе экземпляра родительского класса.

Этот процесс продолжается вверх по цепочке до тех пор, пока не будет найдено совпадение, которое затем возвращается.

Что делает метод find

Учитывая вышеизложенное, метод find в PropertyFinder реализует этот механизм, позволяющий получить список свойств путем рекурсивного изучения __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], чтобы удалить их.
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3