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

IT技术 javascript object methods
2021-01-30 07:00:58

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

 alert(show_all_methods(Math));

这应该打印:

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

您可以使用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不是内置的对象,它们由浏览器定义,并且很可能通过设计可枚举。

ECMA-262 第 3 版开始

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

• 内置对象,例如Math、String、Date、parseInt 等。它们具有属性{DontEnum}
• 其他主机定义的属性。这可能包括一个属性,其值为全局对象本身;例如,在 HTML 文档对象模型中,全局对象的 window 属性就是全局对象本身。

随着控制进入执行上下文,并且随着 ECMAScript 代码的执行,额外的属性可能会被添加到全局对象中,并且初始属性可能会发生变化。

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


更新:一个老乡SO用户,CMS,带来了一个关于IE漏洞{ DontEnum }引起我的注意。

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

简而言之,在命名对象属性时要小心。如果存在同名的内置原型属性或方法,则 IE 将在使用for...in循环时跳过它

@d11wtq,使用 ES5 实现,您可以调用Object.getOwnPropertyNames(),它甚至会返回不可枚举的属性和方法。
2021-03-13 07:00:58
因为所有对象都继承自它们的原型,所以做类似的事情不是更好 Object.getOwnPropertyNames(Array.prototype) 吗?
2021-03-15 07:00:58
安迪 E,感谢您指出这一点。显然我没有意识到这一点,我感谢你努力挖掘出来并在这里提到它。再次感谢 :)
2021-03-17 07:00:58
没有办法在较新的 JS 实现中获得所有方法的列表吗?喜欢 Node.js 和 V8?我们如何像过去那样进行反射和内省对象,例如模拟对象框架等?我以为我只是忘记了 JS,但我想这些年来情况已经发生了变化:)
2021-03-25 07:00:58
@罗兰:不用担心。也许有点难过,但我的文档文件夹中存储了规范,所以实际上不需要太多挖掘!
2021-03-28 07:00:58

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"]没有特定的顺序登录

@Andy - 微软非常重视 IE9,这让我很高兴 :)
2021-03-15 07:00:58
getOwnPropertyNames 是票证。它甚至适用于 Nashorn。他们只是更改了 Java 对象方法的名称,我能够通过运行 Object.getOwnPropertyNames(Java) 找出新名称
2021-03-23 07:00:58
+1 表示 ES5 的东西。IE9 应该会完全支持 ES5,所以这些东西很高兴知道。
2021-03-26 07:00:58
console.log(function(a){return Object.getOwnPropertyNames(a).filter(function(b){return"function"==typeof a[b]})}(Math)); 谢谢!
2021-03-29 07:00:58
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我会得到更多的运气。坦率地说,这有点出乎意料,我不知道为什么它不适用于数学等。
2021-03-16 07:00:58
@Mic:Math 是一个内置对象,其属性不可枚举。
2021-03-16 07:00:58
@Roland:这是因为documentwindow是浏览器提供的具有可枚举属性的对象,它们不是脚本运行时的一部分。本机对象显然是不可枚举的。
2021-04-03 07:00:58
@Roland:抱歉,我的意思是很明显它们不可枚举,因为它们没有出现在 for-in 中。请参阅下面我的回答以获取规范中的引述。
2021-04-03 07:00:58
任何E,我不同意这是显而易见的。我的意思是,这很明显,因为我们似乎无法枚举它们。但是我不明白为什么这些内置函数应该阻止枚举其属性的逻辑。只是好奇,标准的某些部分是否说这些内置函数不应该具有可枚举的属性?
2021-04-07 07:00:58

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

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

这里的其他答案适用于 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/3xrsad0/

不适用于原始问题(数学)之类的问题,因此请根据您的需要选择解决方案。我在这里发布这个是因为谷歌给我发了这个问题,但我想知道如何为对象实例做到这一点。