객체의 모든 방법을 표시하는 방법?


249

예를 들어 객체에 사용할 수있는 모든 메소드를 나열하는 방법을 알고 싶습니다.

 alert(show_all_methods(Math));

인쇄해야합니다 :

abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, 

답변:


298

Object.getOwnPropertyNames()열거 가능 여부에 관계없이 객체에 속하는 모든 속성을 가져 오는 데 사용할 수 있습니다 . 예를 들면 다음과 같습니다.

console.log(Object.getOwnPropertyNames(Math));
//-> ["E", "LN10", "LN2", "LOG2E", "LOG10E", "PI", ...etc ]

그런 다음 filter()메소드 만 얻을 수 있습니다 .

console.log(Object.getOwnPropertyNames(Math).filter(function (p) {
    return typeof Math[p] === 'function';
}));
//-> ["random", "abs", "acos", "asin", "atan", "ceil", "cos", "exp", ...etc ]

ES3 브라우저 (IE 8 이하)에서는 내장 객체의 속성을 열거 할 수 없습니다. 내장 windowdocument내장되지 않은 객체 는 브라우저로 정의되며 설계 상 열거 할 수 있습니다.

ECMA-262 Edition 3 부터 :

전역 객체
고유 한 전역 객체 (15.1)가 있으며, 이는 제어가 실행 컨텍스트에 들어가기 전에 생성됩니다. 처음에 전역 객체는 다음과 같은 속성을 갖습니다.

• Math, String, Date, parseInt 등과 같은 내장 객체 . 속성에는 {DontEnum}이 있습니다.
• 추가 호스트 정의 속성. 여기에는 값이 전역 객체 자체 인 속성이 포함될 수 있습니다. 예를 들어 HTML 문서 객체 모델에서 전역 객체의 window 속성은 전역 객체 자체입니다.

컨트롤이 실행 컨텍스트에 들어가고 ECMAScript 코드가 실행될 때 추가 속성이 전역 객체에 추가되고 초기 속성이 변경 될 수 있습니다.

이것은 객체가 전역 객체의 열거 가능한 속성이 아니라는 것을 의미합니다. 나머지 사양 문서를 살펴보면 이러한 객체의 내장 속성 및 메소드 대부분에 { DontEnum }속성이 설정되어 있음을 알 수 있습니다.


업데이트 : 동료 SO 사용자 인 CMS 는 내 관심 과 관련{ DontEnum } 하여 IE 버그를 가져 왔습니다 .

[Microsoft] JScript는 DontEnum 특성을 확인하는 대신 개체의 프로토 타입 체인에 특성이 DontEnum 인 동일한 이름의 속성이있는 개체의 모든 속성을 건너 뜁니다.

즉, 객체 속성의 이름을 지정할 때주의하십시오. 이름이 같은 내장 프로토 타입 속성 또는 메서드가있는 경우 IE는 for...in루프를 사용할 때 건너 뜁니다 .


앤디 E, 이것을 지적 해 주셔서 감사합니다. 분명히 나는 ​​이것을 알지 못했고 이것을 파고 여기에서 언급하기위한 당신의 노력에 감사드립니다. 다시 한 번 감사드립니다 :)
롤랜드 보우만

@Roland : 걱정 마세요. 어쩌면 조금 슬프지 만 문서 폴더에 사양이 저장되어 있으므로 실제로 파기가 많이 필요하지 않습니다!
Andy E

그렇다면 최신 JS 구현에서 모든 메소드 목록을 가져올 방법이 없습니까? Node.js와 V8처럼? 모의 객체 프레임 워크 등과 같이 예전처럼 객체를 반영하고 조사하는 방법은 무엇입니까? 방금 JS를 잊어 버린 줄
알았지

2
ES5 구현을 통해 @ d11wtq를 호출하면 Object.getOwnPropertyNames()열거 할 수 없는 속성과 메서드도 반환 할 수 있습니다 .
Andy E

모든 객체는 프로토 타입에서 상속되므로 다음과 같은 작업을 수행하는 것이 더 좋지 않습니다 Object.getOwnPropertyNames(Array.prototype) .
lfender6445

71

ES3에서는 속성에 DontEnum이러한 속성을 열거하지 못하게 하는 내부 속성이 있으므로 불가능 합니다. 반면 ES5는 속성의 열거 기능을 제어하기위한 속성 설명자를 제공하므로 사용자 정의 속성과 기본 속성은 동일한 인터페이스를 사용하고 동일한 기능을 사용할 수 있습니다. 여기에는 프로그래밍이 불가능한 속성을 프로그래밍 방식으로 볼 수 있습니다.

getOwnPropertyNames함수는 열거 할 수없는 속성을 포함하여 전달 된 객체의 모든 속성을 열거하는 데 사용할 수 있습니다. 그런 다음 간단한 typeof검사를 사용하여 비 기능을 필터링 할 수 있습니다. 불행히도 Chrome은 현재 작동하는 유일한 브라우저입니다.

function getAllMethods(object) {
    return Object.getOwnPropertyNames(object).filter(function(property) {
        return typeof object[property] == 'function';
    });
}

console.log(getAllMethods(Math));

["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"]특정 순서로 로그인 하지 않습니다.


ES5 물건 +1 IE9는 ES5를 완벽하게 지원하므로이 내용을 잘 알고 있어야합니다.
Andy E

1
@Andy-Microsoft는 IE9를 매우 진지하게 받아들이고 있습니다. :)
Anurag

console.log (function (a) {return Object.getOwnPropertyNames (a) .filter (function (b) {return "function"== 유형 [b]})}} (수학); 감사합니다!
19 시간

1
getOwnPropertyNames는 티켓입니다. 심지어 Nashorn에서도 작동합니다. 방금 Java 객체의 메소드 이름을 변경했으며 Object.getOwnPropertyNames (Java)
cayhorstmann

60
var methods = [];
for (var m in obj) {
    if (typeof obj[m] == "function") {
        methods.push(m);
    }
}
alert(methods.join(","));

이 방법으로 호출 할 수있는 모든 메소드를 얻을 수 있습니다 obj. 여기에는 프로토 타입에서 "상속"하는 메소드가 포함됩니다 (예 getMethods(): java). 직접 정의한 메소드 만 보려면 obj다음을 확인하십시오 hasOwnProperty.

var methods = [];
for (var m in obj) {        
    if (typeof obj[m] == "function" && obj.hasOwnProperty(m)) {
        methods.push(m);
    }
}
alert(methods.join(","));

그래, 나도 그걸 알아 차리고있어 내가 좋아하는 것을 사용 document하거나 window더 많은 운을 얻는다. 솔직히이 조금 뜻밖이다, 나는 그것이 등 수학 작동하지 않는 이유를 모르겠어요
롤랜드 보우만

4
@Roland : 그것은 때문이다 documentwindow브라우저에서 제공하는 열거 속성을 가진 개체, 그들은 스크립팅 런타임의 일부가 아닙니다. 기본 객체는 물론 속성을 열거 할 수 없습니다.
Andy E

1
어떤 E, 나는 그것이 명백하다는 것에 동의하지 않습니다. 우리가 그것들을 열거 할 수 없기 때문에 분명합니다. 그러나 이러한 내장 기능이 속성의 열거를 방지 해야하는 이유에 대한 논리를 보지 못했습니다. 궁금한 점은 표준에 열거 된 속성이 없어야한다고 말하는 부분이 있습니까?
롤랜드 보 우먼

@Roland : 죄송합니다. for-in으로 표시되지 않으므로 열거 할 수 없다는 것이 분명했습니다. 사양의 인용문은 아래 내 답변을 참조하십시오.
Andy E

@Mic : Math는 속성을 열거 할 수없는 내장 객체입니다.
Andy E

31

대부분의 최신 브라우저 지원 console.dir(obj)은 생성자를 통해 상속 된 객체의 모든 속성을 반환합니다. 자세한 정보 및 현재 브라우저 지원에 대해서는 Mozilla 설명서 를 참조하십시오 .

console.dir(Math)
=> MathConstructor
E: 2.718281828459045
LN2: 0.6931471805599453
...
tan: function tan() { [native code] }
__proto__: Object

4

다른 답변은 정적 객체 인 Math와 같은 것에서 작동합니다. 그러나 날짜와 같은 객체 의 인스턴스 에서는 작동하지 않습니다 . 나는 다음을 발견했다.

function getMethods(o) {
  return Object.getOwnPropertyNames(Object.getPrototypeOf(o))
    .filter(m => 'function' === typeof o[m])
}
//example: getMethods(new Date()):  [ 'getFullYear', 'setMonth', ... ]

https://jsfiddle.net/3xrsead0/

이것은 원래의 질문 (Math)과 같은 경우 에는 효과 가 없으므로 필요에 따라 솔루션을 선택하십시오. Google 이이 질문에 저를 보냈기 때문에 여기에 게시하고 있지만 객체 인스턴스에 대해이 작업을 수행하는 방법을 알고 싶었습니다.


3

짧은 대답은 할 수 없기 때문이다 MathDate(내 머리 위로 떨어져, 나는 확실히 다른 사람이 거기에있어이) 정상 개체를 are't. 이것을 보려면 간단한 테스트 스크립트를 작성하십시오.

<html>
  <body>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
      $(function() {
        alert("Math: " + Math);
        alert("Math: " + Math.sqrt);
        alert("Date: " + Date);
        alert("Array: " + Array);
        alert("jQuery: " + jQuery);
        alert("Document: " + document);
        alert("Document: " + document.ready);
      });
    </script>
  </body>
</html>

문서 전체와 동일한 방식으로 객체로 표시되는 것을 볼 수 있지만 실제로 해당 객체에서 시도하고 볼 때 기본 코드이며 열거와 동일한 방식으로 노출되지 않는 것이 있습니다.


1

Math당신처럼 직접 호출 할 수있는 정적 메서드가 Math.abs()있는 동안 Date정적과 같은 방법이 있습니다 Date.now()먼저 새 인스턴스를 만들 필요가 있고 또한 인스턴스 메서드 var time = new Date()호출을 time.getHours().

// The instance method of Date can be found on `Date.prototype` so you can just call:
var keys = Object.getOwnPropertyNames(Date.prototype);

// And for the static method
var keys = Object.getOwnPropertyNames(Date);

// But if the instance already created you need to
// pass its constructor
var time = new Date();
var staticKeys = Object.getOwnPropertyNames(time.constructor);
var instanceKeys = Object.getOwnPropertyNames(time.constructor.prototype);

물론 정적 메소드에 대해 얻은 키 를 필터링 하여 실제 메소드 이름을 가져와야 length, name합니다. 목록의 함수가 아닌 것도 얻을 수 있기 때문 입니다.

그러나 다른 클래스를 확장하는 클래스에서 사용 가능한 모든 메소드를 얻으려면 어떻게해야합니까?
물론을 사용하는 것처럼 프로토 타입의 루트를 스캔해야합니다 __proto__. 시간을 절약하기 위해 아래 스크립트를 사용하여 정적 메소드 및 딥 메소드 인스턴스를 얻을 수 있습니다.

// var keys = new Set();
function getStaticMethods(keys, clas){
    var keys2 = Object.getOwnPropertyNames(clas);

    for(var i = 0; i < keys2.length; i++){
        if(clas[keys2[i]].constructor === Function)
            keys.add(keys2[i]);
    }
}

function getPrototypeMethods(keys, clas){
    if(clas.prototype === void 0)
        return;

    var keys2 = Object.getOwnPropertyNames(clas.prototype);
    for (var i = keys2.length - 1; i >= 0; i--) {
        if(keys2[i] !== 'constructor')
            keys.add(keys2[i]);
    }

    var deep = Object.getPrototypeOf(clas);
    if(deep.prototype !== void 0)
        getPrototypeMethods(keys, deep);
}

// ====== Usage example ======
// To avoid duplicate on deeper prototype we use `Set`
var keys = new Set();
getStaticMethods(keys, Date);
getPrototypeMethods(keys, Date);

console.log(Array.from(keys));

생성 된 인스턴스에서 메소드를 얻으려면 그 메소드를 전달하는 것을 잊지 마십시오 constructor.


0

예를 들어 Array와 같은 내장 객체의 메소드를 열거 할 수없는 역사적인 이유가 있다고 생각합니다. 이유는 다음과 같습니다.

메소드는 프로토 타입 객체의 속성입니다 (예 : Object.prototype). 즉, 모든 객체 인스턴스가 해당 메소드를 상속합니다. 따라서 모든 객체에서 해당 방법을 사용할 수 있습니다. 예를 들어 .toString ()이라고 말하십시오.

따라서 IF 메소드를 열거 할 수 있었고 "for (key in {a : 123}) {...}"로 {a : 123}을 반복하여 어떻게됩니까? 루프가 몇 번 실행됩니까?

이 예에서는 단일 키 'a'에 대해 한 번 반복됩니다. 그러나 Object.prototype의 열거 가능한 모든 속성에 대해 한 번도 . 따라서 메소드를 열거 할 수있는 경우 (기본적으로) 모든 오브젝트의 루프는 상속 된 모든 메소드를 반복합니다.


1
프리미티브은 일반적으로 protype에서 상속 이후이 가능하다 Object.getOwnPropertyNames(Array.prototype)예를 들면
lfender6445

메소드가 Object.prototype의 속성이라는 것은 무엇을 의미합니까? ? 모든 속성은 Object의 경우 Object.prototype의 속성입니다
debugmode
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.