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

Gee*_*tra 232 javascript methods object

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

 alert(show_all_methods(Math));
Run Code Online (Sandbox Code Playgroud)

这应该打印:

abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, …
Run Code Online (Sandbox Code Playgroud)

And*_*y E 279

您可以使用Object.getOwnPropertyNames()获取属于对象的所有属性,无论是否可枚举.例如:

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

然后,您可以使用filter()仅获取方法:

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

在ES3浏览器(IE 8及更低版本)中,内置对象的属性不可枚举.对象喜欢windowdocument不是内置的,它们由浏览器定义,很可能是设计可枚举的.

来自ECMA-262 Edition 3:

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

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

当控件进入执行上下文时,并且当执行ECMAScript代码时,可以向全局对象添加附加属性,并且可以更改初始属性.

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


更新:一个SO用户,CMS,引起了我的注意力IE漏洞{ DontEnum }.

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

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

  • @ d11wtq,使用ES5实现,您可以调用`Object.getOwnPropertyNames()`,它将返回甚至不可枚举的属性和方法. (2认同)
  • 这对于ES6类的实例不起作用 (2认同)

Anu*_*rag 70

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));
Run Code Online (Sandbox Code Playgroud)

["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"]没有特别的顺序登录.

  • getOwnPropertyNames 是票证。它甚至适用于 Nashorn。他们只是更改了 Java 对象的方法名称,我可以通过运行 Object.getOwnPropertyNames(Java) 找出新名称 (2认同)

Rol*_*man 57

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

这样,您将获得可以调用的所有方法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(","));
Run Code Online (Sandbox Code Playgroud)

  • @Roland:这是因为`document`和`window`是具有浏览器提供的可枚举属性的对象,它们不是脚本运行时的一部分.原生对象显然属性不可枚举. (4认同)

Geo*_*ler 27

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

console.dir(obj)


Cir*_*四事件 12

与 ES6 类和继承配合良好的方法

这可能就是大多数像我这样的 ES6 新手用户在寻找“如何列出对象方法”时的意思。

这已改编自: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("__"));
Run Code Online (Sandbox Code Playgroud)

用法示例:

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())
Run Code Online (Sandbox Code Playgroud)

输出:

[ 'baseMethod', 'myGetter', 'override' ]
Run Code Online (Sandbox Code Playgroud)

请注意它还包括基类的方法,因为大多数用户都希望查看他们可以在对象上调用哪些方法。

此方法也适用于Math对象:

console.log(getMethods(Math))
Run Code Online (Sandbox Code Playgroud)

输出:

[
  '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'
]
Run Code Online (Sandbox Code Playgroud)

在 Node.js 14.17.0 上测试。

  • @user48956我不知道,但https://wsvincent.com/javascript-tilde/解释说,它是二进制否定并将-1转换为0。 (2认同)

Kip*_*Kip 8

这里的其他答案适用于 Math 之类的东西,它是一个静态对象。但是它们不适用于对象的实例,例如日期。我发现以下工作:

function getMethods(o) {
  return Object.getOwnPropertyNames(Object.getPrototypeOf(o))
    .filter(m => 'function' === typeof o[m])
}
//example: getMethods(new Date()):  [ 'getFullYear', 'setMonth', ... ]
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/3xrsad0/

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