Javascript 如何显示一个对象的所有方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2257993/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to display all methods of an object?
提问by GeekTantra
I want to know how to list all methods available for an object like for example:
我想知道如何列出对象的所有可用方法,例如:
alert(show_all_methods(Math));
This should print:
这应该打印:
abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, …
回答by Andy E
You can use Object.getOwnPropertyNames()to get all properties that belong to an object, whether enumerable or not. For example:
您可以使用Object.getOwnPropertyNames()获取属于一个对象的所有属性,无论是否可枚举。例如:
console.log(Object.getOwnPropertyNames(Math));
//-> ["E", "LN10", "LN2", "LOG2E", "LOG10E", "PI", ...etc ]
You can then use filter()to obtain only the methods:
然后,您可以使用filter()仅获取方法:
console.log(Object.getOwnPropertyNames(Math).filter(function (p) {
return typeof Math[p] === 'function';
}));
//-> ["random", "abs", "acos", "asin", "atan", "ceil", "cos", "exp", ...etc ]
In ES3 browsers (IE 8 and lower), the properties of built-in objects aren't enumerable. Objects like windowand documentaren't built-in, they're defined by the browser and most likely enumerable by design.
在 ES3 浏览器(IE 8 及更低版本)中,内置对象的属性不可枚举。类似window和document不是内置的对象,它们由浏览器定义,并且很可能通过设计可枚举。
From ECMA-262 Edition 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.
全局对象
有一个唯一的全局对象 (15.1),它是在控制进入任何执行上下文之前创建的。最初,全局对象具有以下属性:? 内置对象,例如 Math、String、Date、parseInt 等。它们具有属性 { DontEnum }。
? 其他主机定义的属性。这可能包括一个属性,其值为全局对象本身;例如,在 HTML 文档对象模型中,全局对象的 window 属性就是全局对象本身。随着控制进入执行上下文,并且随着 ECMAScript 代码的执行,额外的属性可能会被添加到全局对象中,并且初始属性可能会发生变化。
I should point out that this means those objects aren't enumerable properties of the Global object. If you look through the rest of the specification document, you will see most of the built-in properties and methods of these objects have the { DontEnum }attribute set on them.
我应该指出,这意味着这些对象不是 Global 对象的可枚举属性。如果您查看规范文档的其余部分,您将看到这些对象的大多数内置属性和方法都{ DontEnum }设置了属性。
Update: a fellow SO user, CMS, brought an IE bug regarding { DontEnum }to my attention.
更新:一个老乡SO用户,CMS,带来了一个关于IE漏洞{ DontEnum }引起我的注意。
Instead of checking the DontEnum attribute, [Microsoft] JScript will skip over any property in any object where there is a same-named property in the object's prototype chain that has the attribute DontEnum.
[Microsoft] JScript 将跳过任何对象中的任何属性,而不是检查 DontEnum 属性,只要该对象的原型链中有一个具有 DontEnum 属性的同名属性。
In short, beware when naming your object properties. If there is a built-in prototype property or method with the same name then IE will skip over it when using a for...inloop.
简而言之,在命名对象属性时要小心。如果存在同名的内置原型属性或方法,则 IE 将在使用for...in循环时跳过它。
回答by Anurag
It's not possible with ES3 as the properties have an internal DontEnumattribute which prevents us from enumerating these properties. ES5, on the other hand, provides property descriptors for controlling the enumeration capabilities of properties so user-defined and native properties can use the same interface and enjoy the same capabilities, which includes being able to see non-enumerable properties programmatically.
ES3 不可能,因为属性有一个内部DontEnum属性,它阻止我们枚举这些属性。另一方面,ES5 提供了用于控制属性枚举功能的属性描述符,因此用户定义的属性和本机属性可以使用相同的接口并享有相同的功能,其中包括能够以编程方式查看不可枚举的属性。
The getOwnPropertyNamesfunction can be used to enumerate over all properties of the passed in object, including those that are non-enumerable. Then a simple typeofcheck can be employed to filter out non-functions. Unfortunately, Chrome is the only browser that it works on currently.
该getOwnPropertyNames函数可用于枚举传入对象的所有属性,包括不可枚举的属性。然后typeof可以使用简单的检查来过滤掉非功能。不幸的是,Chrome 是目前唯一可以使用的浏览器。
?function getAllMethods(object) {
return Object.getOwnPropertyNames(object).filter(function(property) {
return typeof object[property] == 'function';
});
}
console.log(getAllMethods(Math));
logs ["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"]in no particular order.
["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"]没有特定的顺序登录。
回答by Roland Bouman
var methods = [];
for (var m in obj) {
if (typeof obj[m] == "function") {
methods.push(m);
}
}
alert(methods.join(","));
This way, you will get all methods that you can call on obj. This includes the methods that it "inherits" from its prototype (like getMethods()in java). If you only want to see those methods defined directly by objyou can check with hasOwnProperty:
这样,您将获得可以调用的所有方法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(","));
回答by Geoff Moller
Most modern browser support console.dir(obj), which will return all the properties of an object that it inherited through its constructor. See Mozilla's documentationfor more info and current browser support.
大多数现代浏览器都支持console.dir(obj),它将返回它通过其构造函数继承的对象的所有属性。有关更多信息和当前浏览器支持,请参阅 Mozilla 的文档。
console.dir(Math)
=> MathConstructor
E: 2.718281828459045
LN2: 0.6931471805599453
...
tan: function tan() { [native code] }
__proto__: Object
回答by Kip
The other answers here work for something like Math, which is a static object. But they don't work for an instanceof an object, such as a date. I found the following to work:
这里的其他答案适用于 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/3xrsead0/
This won'twork for something like the original question (Math), so pick your solution based on your needs. I'm posting this here because Google sent me to this question but I was wanting to know how to do this for instances of objects.
这不适用于原始问题(数学)之类的问题,因此请根据需要选择解决方案。我在这里发布这个是因为谷歌给我发了这个问题,但我想知道如何为对象实例做到这一点。
回答by Nick Craver
The short answer is you can't because Mathand Date(off the top of my head, I'm sure there are others) are't normal objects. To see this, create a simple test script:
简短的回答是你不能,因为Math和Date(在我的脑海里,我确定还有其他的)不是正常的物体。要查看这一点,请创建一个简单的测试脚本:
<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>
You see it presents as an object the same ways document does overall, but when you actually try and see in that object, you see that it's native code and something not exposed the same way for enumeration.
您会看到它以与文档整体相同的方式呈现为对象,但是当您实际尝试查看该对象时,您会发现它是本机代码,并且某些内容没有以相同的方式公开以进行枚举。
回答by StefansArya
Mathhas static method where you can call directly like Math.abs()while Datehas static method like Date.now()and also instance method where you need to create new instance first var time = new Date()to call time.getHours().
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);
Of course you will need to filterthe obtained keys for the static method to get actual method names, because you can also get length, namethat aren't a function on the list.
当然,您需要过滤静态方法获得的键以获取实际方法名称,因为您也可以获取length, name列表中没有的函数。
But how if we want to obtain all available method from class that extend another class?
Of course you will need to scan through the root of prototype like using __proto__. For saving your time you can use script below to get static method and deep method instance.
但是如果我们想从扩展另一个类的类中获取所有可用的方法呢?
当然,您需要像使用__proto__. 为了节省您的时间,您可以使用下面的脚本来获取静态方法和深层方法实例。
// 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));
If you want to obtain methods from created instance, don't forget to pass the constructorof it.
如果你想从创建的实例中获取方法,不要忘记传递constructor它的。
回答by Panu Logic
I believe there's a simple historical reason why you can't enumerate over methods of built-in objects like Array for instance. Here's why:
我相信有一个简单的历史原因,为什么你不能枚举像 Array 这样的内置对象的方法。原因如下:
Methods are properties of the prototype-object, say Object.prototype. That means that all Object-instances will inherit those methods. That's why you can use those methods on any object. Say .toString() for instance.
方法是原型对象的属性,比如 Object.prototype。这意味着所有对象实例都将继承这些方法。这就是为什么您可以在任何对象上使用这些方法的原因。比如说 .toString() 。
So IF methods were enumerable, and I would iterate over say {a:123} with: "for (key in {a:123}) {...}" what would happen? How many times would that loop be executed?
所以 IF 方法是可枚举的,我会重复说 {a:123} :“for (key in {a:123}) {...}”会发生什么?该循环将执行多少次?
It would be iterated once for the single key 'a' in our example. BUT ALSO once for every enumerableproperty of Object.prototype. So if methods were enumerable (by default), then any loop over any object would loop over all its inherited methods as well.
在我们的示例中,它将为单个键 'a' 迭代一次。但对于Object.prototype 的每个可枚举属性也一次。因此,如果方法是可枚举的(默认情况下),那么任何对象上的任何循环也会循环其所有继承的方法。

