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

 alert(show_all_methods(Math));

这应该打印:

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

当前回答

与ES6类和继承很好地工作的方法

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

本文已改编自:https://stackoverflow.com/a/47714550/895245

// Define getMethods.
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("__"));

// Example usage.

class BaseClass {
  override() { }
  baseMethod() { }
}

class DerivedClass extends BaseClass {
  override() { }
  get myGetter() { }
  static myStatic() { }
}

const obj = new DerivedClass();
const methods = getMethods(obj)
methods.sort()
const assert = require('assert')
assert(methods[0] === 'baseMethod')
assert(methods[1] === 'myGetter')
assert(methods[2] === 'override')

console.log(getMethods(Math))

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

它似乎也与Math一起工作,它输出:

[
  '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'
]

在Node.js 14.17.0上测试。

其他回答

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(","));

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

getOwnPropertyNames函数可用于枚举传入对象的所有属性,包括那些不可枚举的属性。然后可以使用一种简单的检查类型来过滤非函数。不幸的是,Chrome是目前唯一可以运行的浏览器。

​function getAllMethods(object) {
    return Object.getOwnPropertyNames(object).filter(function(property) {
        return typeof object[property] == 'function';
    });
}

console.log(getAllMethods(Math));

日志(“因为”、“战俘”、“日志”,“晒”,“√”,“装天花板”、“最佳”、“abs”、“max”、“实验”、“量化”,“随机”,“圆”,“地板”,“治疗”,“世界”,“分”,“罪”)在任何特定的顺序。

如果你想要包括继承方法在内的所有方法:

函数getMethods(obj) { Const方法= []; {做 for (Object.getOwnPropertyNames(obj)的const道具){ if (obj[prop] instanceof Function) method .push(prop); } obj = Object.getPrototypeOf(obj); } while (obj !== null) 回归方法; } console.log (getMethods(数学));

Math有一个静态方法,你可以直接调用Math.abs(),而Date有一个静态方法,比如Date.now(),还有一个实例方法,你需要先创建一个新的实例var time = new Date()来调用time. gethours()。

// The instance method of Date can be found on `Date.prototype` so you can just call:
var keys = Object.getOwnPropertyNames(Date.prototype);

// And for the static method
var keys = Object.getOwnPropertyNames(Date);

// But if the instance already created you need to
// pass its constructor
var time = new Date();
var staticKeys = Object.getOwnPropertyNames(time.constructor);
var instanceKeys = Object.getOwnPropertyNames(time.constructor.prototype);

当然,您将需要过滤静态方法获得的键,以获得实际的方法名称,因为您还可以获得列表中不是函数的长度和名称。

但是,如果我们想从扩展另一个类的类中获得所有可用的方法,该怎么办呢? 当然,你需要像使用__proto__一样扫描prototype的根。为了节省你的时间,你可以使用下面的脚本来获得静态方法和深层方法实例。

// var keys = new Set(); function getStaticMethods(keys, clas){ var keys2 = Object.getOwnPropertyNames(clas); for(var i = 0; i < keys2.length; i++){ if(clas[keys2[i]].constructor === Function) keys.add(keys2[i]); } } function getPrototypeMethods(keys, clas){ if(clas.prototype === void 0) return; var keys2 = Object.getOwnPropertyNames(clas.prototype); for (var i = keys2.length - 1; i >= 0; i--) { if(keys2[i] !== 'constructor') keys.add(keys2[i]); } var deep = Object.getPrototypeOf(clas); if(deep.prototype !== void 0) getPrototypeMethods(keys, deep); } // ====== Usage example ====== // To avoid duplicate on deeper prototype we use `Set` var keys = new Set(); getStaticMethods(keys, Date); getPrototypeMethods(keys, Date); console.log(Array.from(keys));

如果你想从创建的实例中获取方法,不要忘记传递它的构造函数。

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

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

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