>웹 프론트엔드 >JS 튜토리얼 >JavaScript에서 Ruby 메소드 메소드 구현하기

JavaScript에서 Ruby 메소드 메소드 구현하기

WBOY
WBOY원래의
2024-07-31 06:30:131055검색

Implementing Ruby

갑자기 루비의 메소드 메소드가 편하지 않나요? 코드를 작성할 때 개체에 사용할 수 있는 모든 메서드와 속성을 나열하고 이를 검색할 수 있으므로 디버깅에 매우 유용합니다.

그 외에도 Rails와 같은 프레임워크에 특정한 방법을 확인하고 코드 읽기 및 라이브러리 이해에 도움이 되는 데에도 효과적입니다. 공식 문서나 소스 코드를 참조하는 것이 좋은 습관이지만, 메소드 메소드는 깊이 들어갈 필요가 없거나 메소드 이름이 모호한 경우 라이브러리에 상당히 유용합니다.

Ruby의 방법 방법

루비의 메소드 메소드를 간략히 소개하자면 다음과 같습니다.

객체#메소드

obj의 공개 및 보호 메서드 이름 목록을 반환합니다. 여기에는 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에서 가장 중요한 메소드는 찾기 메소드입니다. 이 메소드는 주어진 객체의 프로토타입 체인을 순회하여 접근 가능한 속성을 검색하고 이를 목록으로 반환합니다.

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 메소드 메소드 구현하기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.