如何显示对象的所有方法?

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

alert(show_all_methods(Math)); 

这应该打印:

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

您可以使用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类的对象不是内置的,它们是由浏览器定义的,而且很可能是按devise枚举的。

来自ECMA-262第3版 :

全局对象
有一个唯一的全局对象(15.1),它是在控制进入任何执行上下文之前创build的。 最初,全局对象具有以下属性:

•内置对象,如math,string,date,parseInt等, 这些都有属性{DontEnum}
•其他主机定义的属性。 这可能包括一个属性,其价值是全局对象本身; 例如,在HTML文档对象模型中,全局对象的窗口属性是全局对象本身。

当控制进入执行上下文,并且随着ECMAScript代码被执行,附加属性可以被添加到全局对象,并且初始属性可以被改变。

我应该指出,这意味着这些对象不是Global对象的枚举属性。 如果您仔细阅读规范文档的其余部分,您将会看到这些对象的大部分内置属性和方法都在其上设置了{ DontEnum }属性。


更新:一位SO用户CMS(CMS { DontEnum }为我引起了关于{ DontEnum }的IE错误 。

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

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

这是不可能的ES3的属性有一个内部的DontEnum属性,这阻止我们枚举这些属性。 另一方面,ES5提供了属性描述符来控制属性的枚举能力,因此用户定义和本机属性可以使用相同的接口并享有相同的function,其中包括能够以编程方式查看非枚举属性。

getOwnPropertyNames函数可用于枚举传入对象的所有属性,包括那些不可枚举的属性。 然后可以使用简单的检查来过滤掉非function。 不幸的是,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所有方法。 这包括它从原型“inheritance”的方法(如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(",")); 

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

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

简短的答案是你不能因为MathDate (我的头顶,我敢肯定还有其他人)是不正常的对象。 要看到这个,创build一个简单的testing脚本:

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

你会发现它以一个对象的forms呈现出与文档总体上相同的方式,但是当你真的试图在这个对象中看到的时候,你会发现它是本地代码,并且没有以相同的方式公开枚举。

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

方法是原型对象的属性,比如Object.prototype。 这意味着所有的对象实例都将inheritance这些方法。 这就是为什么你可以在任何对象上使用这些方法。 说例如.toString()。

因此,IF方法是可枚举的,我将迭代{a:123}用:“for(key in {a:123}){…}”会发生什么? 该循环将被执行多less次?

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