답변:
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 이하)에서는 내장 객체의 속성을 열거 할 수 없습니다. 내장 window
및 document
내장되지 않은 객체 는 브라우저로 정의되며 설계 상 열거 할 수 있습니다.
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
루프를 사용할 때 건너 뜁니다 .
Object.getOwnPropertyNames()
열거 할 수 없는 속성과 메서드도 반환 할 수 있습니다 .
Object.getOwnPropertyNames(Array.prototype)
.
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"]
특정 순서로 로그인 하지 않습니다.
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
더 많은 운을 얻는다. 솔직히이 조금 뜻밖이다, 나는 그것이 등 수학 작동하지 않는 이유를 모르겠어요
document
과 window
브라우저에서 제공하는 열거 속성을 가진 개체, 그들은 스크립팅 런타임의 일부가 아닙니다. 기본 객체는 물론 속성을 열거 할 수 없습니다.
다른 답변은 정적 객체 인 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 이이 질문에 저를 보냈기 때문에 여기에 게시하고 있지만 객체 인스턴스에 대해이 작업을 수행하는 방법을 알고 싶었습니다.
짧은 대답은 할 수 없기 때문이다 Math
과 Date
(내 머리 위로 떨어져, 나는 확실히 다른 사람이 거기에있어이) 정상 개체를 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>
문서 전체와 동일한 방식으로 객체로 표시되는 것을 볼 수 있지만 실제로 해당 객체에서 시도하고 볼 때 기본 코드이며 열거와 동일한 방식으로 노출되지 않는 것이 있습니다.
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
.
예를 들어 Array와 같은 내장 객체의 메소드를 열거 할 수없는 역사적인 이유가 있다고 생각합니다. 이유는 다음과 같습니다.
메소드는 프로토 타입 객체의 속성입니다 (예 : Object.prototype). 즉, 모든 객체 인스턴스가 해당 메소드를 상속합니다. 따라서 모든 객체에서 해당 방법을 사용할 수 있습니다. 예를 들어 .toString ()이라고 말하십시오.
따라서 IF 메소드를 열거 할 수 있었고 "for (key in {a : 123}) {...}"로 {a : 123}을 반복하여 어떻게됩니까? 루프가 몇 번 실행됩니까?
이 예에서는 단일 키 'a'에 대해 한 번 반복됩니다. 그러나 Object.prototype의 열거 가능한 모든 속성에 대해 한 번도 . 따라서 메소드를 열거 할 수있는 경우 (기본적으로) 모든 오브젝트의 루프는 상속 된 모든 메소드를 반복합니다.
Object.getOwnPropertyNames(Array.prototype)
예를 들면