330

I want to know how to list all methods available for an object like for example:

 alert(show_all_methods(Math)); 

This should print:

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

11 Answers 11

390

You can use Object.getOwnPropertyNames() to get all properties that belong to an object, whether enumerable or not. For example:

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

You can then use filter() to obtain only the methods:

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

In ES3 browsers (IE 8 and lower), the properties of built-in objects aren't enumerable. Objects like window and document aren't built-in, they're defined by the browser and most likely enumerable by design.

From ECMA-262 Edition 3:

Global Object
There is a unique global object (15.1), which is created before control enters any execution context. Initially the global object has the following properties:

• Built-in objects such as Math, String, Date, parseInt, etc. These have attributes { DontEnum }.
• Additional host defined properties. This may include a property whose value is the global object itself; for example, in the HTML document object model the window property of the global object is the global object itself.

As control enters execution contexts, and as ECMAScript code is executed, additional properties may be added to the global object and the initial properties may be changed.

I should point out that this means those objects aren't enumerable properties of the Global object. If you look through the rest of the specification document, you will see most of the built-in properties and methods of these objects have the { DontEnum } attribute set on them.


Update: a fellow SO user, CMS, brought an IE bug regarding { DontEnum } to my attention.

Instead of checking the DontEnum attribute, [Microsoft] JScript will skip over any property in any object where there is a same-named property in the object's prototype chain that has the attribute DontEnum.

In short, beware when naming your object properties. If there is a built-in prototype property or method with the same name then IE will skip over it when using a for...in loop.

Sign up to request clarification or add additional context in comments.

10 Comments

Andy E, thanks for pointing this out. Clearly i was not aware of this and I appreciate your effort for digging this out and mentioning it here. Thanks again :)
@Roland: No worries. Maybe it's a little sad, but I have the specification stored in my Documents folder, so not much digging required really!
Is there no way to get a list of all methods in newer JS implementations, then? Like Node.js and V8? How do we do reflection and introspect objects like we used to do, such as for mock object frameworks etc? I thought I'd just forgotten JS, but I guess things have changed over the years :)
@d11wtq, with ES5 implementations, you can invoke Object.getOwnPropertyNames(), which will return even non-enumerable properties and methods.
since all objects inherit from their prototype, wouldn't it be better to do something like Object.getOwnPropertyNames(Array.prototype) ?
|
77

It's not possible with ES3 as the properties have an internal DontEnum attribute which prevents us from enumerating these properties. ES5, on the other hand, provides property descriptors for controlling the enumeration capabilities of properties so user-defined and native properties can use the same interface and enjoy the same capabilities, which includes being able to see non-enumerable properties programmatically.

The getOwnPropertyNames function can be used to enumerate over all properties of the passed in object, including those that are non-enumerable. Then a simple typeof check can be employed to filter out non-functions. Unfortunately, Chrome is the only browser that it works on currently.

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

logs ["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"] in no particular order.

4 Comments

+1 for the ES5 stuff. IE9 will supposedly fully support ES5 so this stuff is good to know.
@Andy - Microsoft is taking IE9 very seriously which makes me happy :)
console.log(function(a){return Object.getOwnPropertyNames(a).filter(function(b){return"function"==typeof a[b]})}(Math)); Thank you!
getOwnPropertyNames is the ticket. It even works in Nashorn. They just changed the names of the methods of the Java object, and I was able to figure out the new names by running Object.getOwnPropertyNames(Java)
67
var methods = []; for (var m in obj) { if (typeof obj[m] == "function") { methods.push(m); } } alert(methods.join(",")); 

This way, you will get all methods that you can call on obj. This includes the methods that it "inherits" from its prototype (like getMethods() in java). If you only want to see those methods defined directly by obj you can check with hasOwnProperty:

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

6 Comments

yeah, I'm just noticing that too. When I use somethting like document or window i get more luck. Frankly it is a bit unexpected, I don't know why it doesn't work for Math etc.
@Roland: It's because document and window are objects with enumerable properties provided by the browser, they're not part of the scripting runtime. Native objects are and obviously the properties aren't enumerable.
Any E, i don't agree it's obvious. I mean, it is apparent since we can't seem to enumerate them. But I don't see the logic as to why those built-ins should prevent enumeration of their properties. Just curious, is there some part of the standard that says these built-ins should not have enumerable properties?
@Roland: sorry, I meant that it's obvious they're not enumerable since they don't show up with a for-in. See my answer below for a quote from the spec.
@Mic: Math is a built-in object whose properties aren't enumerable.
|
35

Most modern browser support console.dir(obj), which will return all the properties of an object that it inherited through its constructor. See Mozilla's documentation for more info and current browser support.

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

Comments

25

The other answers here work for something like Math, which is a static object. But they don't work for an instance of an object, such as a date. I found the following to work:

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/

This won't work for something like the original question (Math), so pick your solution based on your needs. I'm posting this here because Google sent me to this question but I was wanting to know how to do this for instances of objects.

Comments

15

Approach that works nicely with ES6 classes and inheritance

This is likely what most newbie ES6 users like me mean when they are looking for "how to list object methods".

This has been adapted from: https://stackoverflow.com/a/47714550/895245

const isGetter = (x, name) => (Object.getOwnPropertyDescriptor(x, name) || {}).get const isFunction = (x, name) => typeof x[name] === "function"; const deepFunctions = x => x && x !== Object.prototype && Object.getOwnPropertyNames(x) .filter(name => isGetter(x, name) || isFunction(x, name)) .concat(deepFunctions(Object.getPrototypeOf(x)) || []); const distinctDeepFunctions = x => Array.from(new Set(deepFunctions(x))); const getMethods = (obj) => distinctDeepFunctions(obj).filter( name => name !== "constructor" && !~name.indexOf("__")); 

Example usage:

class BaseClass { override() { } baseMethod() { } } class DerivedClass extends BaseClass { override() { } get myGetter() { } static myStatic() { } } const obj = new DerivedClass(); const methods = getMethods(obj) console.log(methods.sort()) 

Output:

[ 'baseMethod', 'myGetter', 'override' ] 

Note how it also includes methods of base classes as most users will want to see which methods they can call on the object.

This method also works fine with the Math object:

console.log(getMethods(Math)) 

output:

[ 'abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'atan2', 'ceil', 'cbrt', 'expm1', 'clz32', 'cos', 'cosh', 'exp', 'floor', 'fround', 'hypot', 'imul', 'log', 'log1p', 'log2', 'log10', 'max', 'min', 'pow', 'random', 'round', 'sign', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc' ] 

Tested on Node.js 14.17.0.

8 Comments

@user48956 I didn't know, but wsvincent.com/javascript-tilde explained, it's binary negation and converts -1 to 0.
Yes -- but its a little unusual to use binary negation unless you're dealing with bit-manipulations of numbers (for all other cases, usually use boolean negation: !)
@user48956 performance is for beginners, real pros only care about code golfing
This worked well for me! Here's the above, converted into TypeScript -- gist.github.com/matthew-dean/9267ab91b0c701cfb956f7f0c1549b55
This is awesome. For some reason, my methods were clouded, but the answer just works the best.
|
4

Math has static method where you can call directly like Math.abs() while Date has static method like Date.now() and also instance method where you need to create new instance first var time = new Date() to call 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); 

Of course you will need to filter the obtained keys for the static method to get actual method names, because you can also get length, name that aren't a function on the list.

But how if we want to obtain all available method from class that extend another class?
Of course you will need to scan through the root of prototype like using __proto__. For saving your time you can use script below to get static method and deep method instance.

// 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));

If you want to obtain methods from created instance, don't forget to pass the constructor of it.

Comments

2

The short answer is you can't because Math and Date (off the top of my head, I'm sure there are others) are't normal objects. To see this, create a simple test script:

<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> 

You see it presents as an object the same ways document does overall, but when you actually try and see in that object, you see that it's native code and something not exposed the same way for enumeration.

Comments

1

I believe there's a simple historical reason why you can't enumerate over methods of built-in objects like Array for instance. Here's why:

Methods are properties of the prototype-object, say Object.prototype. That means that all Object-instances will inherit those methods. That's why you can use those methods on any object. Say .toString() for instance.

So IF methods were enumerable, and I would iterate over say {a:123} with: "for (key in {a:123}) {...}" what would happen? How many times would that loop be executed?

It would be iterated once for the single key 'a' in our example. BUT ALSO once for every enumerable property of Object.prototype. So if methods were enumerable (by default), then any loop over any object would loop over all its inherited methods as well.

2 Comments

since primitives usually inherit from a protype, this is possible Object.getOwnPropertyNames(Array.prototype) for example
what do you mean methods are properties of Object.prototype. ? Every property is properties of Object.prototype in case of Object
1

Inspired by the other answers, here's a recursive way of finding all methods:

// Find all methods of an object, up to the root prototype function findAllMethods(obj, methods = []) { if (!obj) { return [...new Set(methods)]; } const props = Object.getOwnPropertyNames(obj); return findAllMethods(Object.getPrototypeOf(obj), [ ...methods, ...props.filter(prop => typeof obj[prop] === 'function'), ]); } 

Comments

0

If you want all methods including inherited ones:

function getMethods(obj) { const methods = []; do { for (const prop of Object.getOwnPropertyNames(obj)) { if (obj[prop] instanceof Function) methods.push(prop); } obj = Object.getPrototypeOf(obj); } while (obj !== null) return methods; } console.log(getMethods(Math));

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.