Javascript 获取类的函数(方法)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31054910/
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
Get functions (methods) of a class
提问by Jan
I have to dynamically fetch the properties and functions of a ES6 class. Is this even possible?
我必须动态获取 ES6 类的属性和函数。这甚至可能吗?
Using a for...in loop, I only get to loop through the properties of a class instance:
使用 for...in 循环,我只能循环遍历类实例的属性:
class Foo {
constructor() {
this.bar = "hi";
}
someFunc() {
console.log(this.bar);
}
}
var foo = new Foo();
for (var idx in foo) {
console.log(idx);
}
Output:
输出:
bar
采纳答案by Muhammad Umer
This function will get all functions. Inherited or not, enumerable or not. All functions are included.
此函数将获取所有函数。继承与否,可枚举与否。所有功能都包括在内。
function getAllFuncs(toCheck) {
var props = [];
var obj = toCheck;
do {
props = props.concat(Object.getOwnPropertyNames(obj));
} while (obj = Object.getPrototypeOf(obj));
return props.sort().filter(function(e, i, arr) {
if (e!=arr[i+1] && typeof toCheck[e] == 'function') return true;
});
}
Do test
做测试
getAllFuncs([1,3]);
getAllFuncs([1,3]);
console output:
控制台输出:
["constructor", "toString", "toLocaleString", "join", "pop", "push", "concat", "reverse", "shift", "unshift", "slice", "splice", "sort", "filter", "forEach", "some", "every", "map", "indexOf", "lastIndexOf", "reduce", "reduceRight", "entries", "keys", "constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "__defineGetter__", "__lookupGetter__", "__defineSetter__", "__lookupSetter__"]
Note
笔记
It doesn't return functions defined via symbols;
它不返回通过符号定义的函数;
回答by Felix Kling
The members of a class are not enumerable. To get them, you have to use Object.getOwnPropertyNames
:
类的成员不可枚举。要获得它们,您必须使用Object.getOwnPropertyNames
:
var propertyNames = Object.getOwnPropertyNames(Object.getPrototypeOf(foo));
// or
var propertyNames = Object.getOwnPropertyNames(Foo.prototype);
Of course this won't get inherited methods. There is no method that can give you all of them. You'd have to traverse the prototype chain and get the properties for each prototype individually.
当然,这不会得到继承的方法。没有任何方法可以为您提供所有这些。您必须遍历原型链并分别获取每个原型的属性。
回答by skav
ES6 adds Reflection which makes the code to do this a bit cleaner.
ES6 添加了反射,这使得代码更清晰。
function getAllMethodNames(obj) {
let methods = new Set();
while (obj = Reflect.getPrototypeOf(obj)) {
let keys = Reflect.ownKeys(obj)
keys.forEach((k) => methods.add(k));
}
return methods;
}
/// a simple class hierarchy to test getAllMethodNames
// kind of like an abstract base class
class Shape {
constructor() {}
area() {
throw new Error("can't define area for generic shape, use a subclass")
}
}
// Square: a shape with a sideLength property, an area function and getSideLength function
class Square extends Shape {
constructor(sideLength) {
super();
this.sideLength = sideLength;
}
area() {
return this.sideLength * this.sideLength
};
getSideLength() {
return this.sideLength
};
}
// ColoredSquare: a square with a color
class ColoredSquare extends Square {
constructor(sideLength, color) {
super(sideLength);
this.color = color;
}
getColor() {
return this.color
}
}
let temp = new ColoredSquare(2, "red");
let methods = getAllMethodNames(temp);
console.log([...methods]);
回答by Bruno Grieder
There were a few issues in @MuhammadUmer answer for me (symbols, index i+1
, listing of Object
methods, etc...) so taking inspiration from it, I came up with this
@MuhammadUmer 对我的回答有一些问题(符号、索引i+1
、Object
方法列表等...),所以从中汲取灵感,我想出了这个
(warning Typescript compiled to ES6)
(警告 Typescript 编译为 ES6)
const getAllMethods = (obj) => {
let props = []
do {
const l = Object.getOwnPropertyNames(obj)
.concat(Object.getOwnPropertySymbols(obj).map(s => s.toString()))
.sort()
.filter((p, i, arr) =>
typeof obj[p] === 'function' && //only the methods
p !== 'constructor' && //not the constructor
(i == 0 || p !== arr[i - 1]) && //not overriding in this prototype
props.indexOf(p) === -1 //not overridden in a child
)
props = props.concat(l)
}
while (
(obj = Object.getPrototypeOf(obj)) && //walk-up the prototype chain
Object.getPrototypeOf(obj) //not the the Object prototype methods (hasOwnProperty, etc...)
)
return props
}
This function will list allmethods of an instance of the class including those inherited, butthe constructor and those of the Object prototype.
此函数将列出类实例的所有方法,包括继承的方法,但构造函数和对象原型的方法。
Test
测试
The function returns
函数返回
[ 'asyncMethod',
'echo',
'generatorMethod',
'ping',
'pong',
'anotherEcho' ]
listing the methods of an instance of TestClass
(typescript)
列出TestClass
(打字稿)实例的方法
class Echo {
echo(data: string): string {
return data
}
anotherEcho(data: string): string {
return `Echo ${data}`
}
}
class TestClass extends Echo {
ping(data: string): string {
if (data === 'ping') {
return 'pong'
}
throw new Error('"ping" was expected !')
}
pong(data: string): string {
if (data === 'pong') {
return 'ping'
}
throw new Error('"pong" was expected !')
}
//overridden echo
echo(data: string): string {
return 'blah'
}
async asyncMethod(): Promise<string> {
return new Promise<string>((resolve: (value?: string) => void, reject: (reason?: any) => void) => {
resolve('blah')
})
}
* generatorMethod(): IterableIterator<string> {
yield 'blah'
}
}
回答by Santinell
To make members of class enumerable you can use Symbol.iterator
要使类的成员可枚举,您可以使用 Symbol.iterator
I had to get all allowed methods of object (including inherited). So i created class "Enumerable" and all my base classes inherited from him.
我必须获得所有允许的对象方法(包括继承的)。所以我创建了“Enumerable”类和我从他那里继承的所有基类。
class Enumerable {
constructor() {
// Add this for enumerate ES6 class-methods
var obj = this;
var getProps = function* (object) {
if (object !== Object.prototype) {
for (let name of Object.getOwnPropertyNames(object)) {
let method = object[name];
// Supposedly you'd like to skip constructor and private methods (start with _ )
if (method instanceof Function && name !== 'constructor' && name[0] !== '_')
yield name;
}
yield* getProps(Object.getPrototypeOf(object));
}
}
this[Symbol.iterator] = function*() {
yield* getProps(obj);
}
// --------------
}
}