我想知道如何列出一个对象可用的所有方法,例如:

 alert(show_all_methods(Math));

这应该打印:

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

当前回答

我相信有一个简单的历史原因,为什么你不能列举 使用内置对象的方法,例如Array。原因如下:

方法是prototype-object的属性,比如Object.prototype。 这意味着所有object实例都将继承这些方法。这是 为什么你可以在任何对象上使用这些方法。例如,使用. tostring()。

所以IF方法是可枚举的,我将遍历{a:123} 使用:"for(输入{a:123}){…会发生什么?多少次 循环会被执行吗?

在我们的例子中,对于单个键“a”,它将被迭代一次。但也 Object.prototype的每个可枚举属性一次。因此,如果 方法是可枚举的(默认情况下),那么在任何对象上的任何循环都将循环 对所有继承的方法也是如此。

其他回答

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

这样,你将得到所有你可以在obj上调用的方法。这包括它从原型中“继承”的方法(如java中的getMethods())。如果你只想看到那些由obj直接定义的方法,你可以用hasOwnProperty检查:

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

简单的回答是,你不能,因为数学和日期(在我的脑海中,我相信还有其他的)不是正常的对象。为了看到这一点,创建一个简单的测试脚本:

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

你可以看到它作为一个对象的表现方式和文档的表现方式是一样的,但是当你真正尝试在那个对象中观察时,你会看到它是原生代码而不是以相同的方式为枚举公开的东西。

您可以使用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浏览器(ie8及以下版本)中,内置对象的属性是不可枚举的。像window和document这样的对象不是内置的,它们是由浏览器定义的,而且很可能是通过设计来枚举的。

来自ECMA-262版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.

我应该指出,这意味着这些对象不是全局对象的可枚举属性。如果查看规范文档的其余部分,您将看到这些对象的大多数内置属性和方法都设置了{DontEnum}属性。


更新:一个SO用户,CMS,给我带来了一个关于{DontEnum}的IE bug。

而不是检查DontEnum属性,[Microsoft] JScript将跳过任何对象中的任何属性,在对象的原型链中有一个具有DontEnum属性的同名属性。

简而言之,在命名对象属性时要小心。如果有一个内置的原型属性或方法具有相同的名称,那么IE将在使用for…在循环。

大多数现代浏览器支持console.dir(obj),它将返回它通过构造函数继承的对象的所有属性。有关更多信息和当前浏览器支持,请参阅Mozilla的文档。

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

受到其他答案的启发,这里有一种查找所有方法的递归方法:

// 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'),
  ]);
}