De repente, o método de métodos do Ruby não é útil? Ao escrever código, ele lista todos os métodos e propriedades disponíveis para um objeto e permite pesquisá-los, o que é muito útil para depuração.
Além disso, também é eficaz para verificar métodos específicos de frameworks como Rails, auxiliando na leitura de código e no entendimento de bibliotecas. Embora seja uma boa prática consultar a documentação oficial ou o código-fonte, o método de métodos é bastante útil para bibliotecas onde você não precisa se aprofundar ou quando tem vagas lembranças de nomes de métodos.
Para apresentar brevemente o método de métodos do Ruby, fica assim:
Objeto#método
Retorna uma lista de nomes de métodos públicos e protegidos de obj. Isso incluirá todos os métodos acessíveis nos ancestrais do obj. Se o parâmetro opcional for falso, ele retornará uma matriz de métodos singleton públicos e protegidos do obj, a matriz não incluirá métodos em módulos incluídos em obj.
Em outras palavras, ele retorna um objeto array das propriedades e métodos acessíveis a partir do receptor.
Este método é implementado na classe Object, que é o ancestral de todas as classes que herdam de Object, portanto pode ser usado em qualquer classe que herde de Object.
Código de amostra
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]
Como mostrado no exemplo, ele retorna um objeto Array, então você também pode pesquisar na lista de métodos usando o método grep, o que é muito conveniente.
Então, pensei se isso poderia ser feito em JS e tentei.
Abaixo está o código real.
O nome da classe pode ser qualquer coisa, mas vou chamá-la de PropertyFinder por enquanto.
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] } }
Explicarei o código mais tarde, mas vamos começar explicando como usá-lo.
Uma vez definida a classe, você pode adicionar um método às propriedades da classe Object da seguinte forma:
Object.prototype.methods = function () { return new PropertyFinder(this) }
Ao fazer isso, você pode usar o método de métodos em instâncias de classes herdadas de Object. No entanto, esteja ciente da nota de cuidado abaixo e use-a por sua própria conta e risco.
Aqui estão alguns exemplos de execuções:
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']
*Este código não é recomendado para uso em ambientes de produção *
Adicionar propriedades a classes de nível superior por meio de patches de macaco é um antipadrão e pode levar a problemas com mudanças futuras nas especificações JS. Use-o com cuidado e por sua própria conta e risco.
Referência: Os contras do patch de macaco
Agora, vamos explicar o código.
O método mais importante no PropertyFinder é o método find. Este método percorre a cadeia de protótipos de um determinado objeto, procura propriedades acessíveis e as retorna como uma lista.
Os métodos toString e grep simplesmente usam find, portanto não precisam de mais explicações.
A cadeia de protótipos pode não ser familiar para alguns, mas é a herança de propriedades da classe Object.
Herança e cadeia de protótipos | MDN
Os detalhes são abordados na documentação do MDN, mas o mecanismo de herança do JavaScript é suportado pela cadeia de protótipos.
Embora nem sempre seja óbvio, quando se refere a alguma propriedade, o processo envolve:
Esse processo continua na cadeia até que uma correspondência seja encontrada, que é então retornada.
Dado o exposto, o método find no PropertyFinder implementa esse mecanismo, permitindo que você obtenha uma lista de propriedades explorando recursivamente __proto__.
Aqui está a implementação que consegue isso explorando __proto__ recursivamente para obter a lista:
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] }
Isso conclui a explicação do PropertyFinder.
Isso encerra a explicação do código e o que eu tentei.
Este foi mais um exercício experimental ou lúdico, mas como envolveu algum conhecimento e técnicas, espero que você o considere útil ou inspirador para suas próprias aplicações.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3