name - javascript print object




How to display all methods of an object? (4)

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.

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

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.


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.


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.







methods