javascript ES6 迭代类方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30881632/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 12:52:52  来源:igfitidea点击:

ES6 Iterate over class methods

javascriptecmascript-6

提问by seasick

Given this class; how would i iterate over the methods that it includes?

鉴于这个类;我将如何迭代它包含的方法?

class Animal {
    constructor(type){
        this.animalType = type;
    }
    getAnimalType(){
        console.log('this.animalType: ', this.animalType );
    }
}

let cat = window.cat = new Animal('cat')

What I have tried is the following with no success:

我尝试过以下但没有成功:

for (var each in Object.getPrototypeOf(cat) ){
    console.log(each);
}

回答by Paul

You can use Object.getOwnPropertyNameson the prototype:

您可以在原型上使用Object.getOwnPropertyNames

Object.getOwnPropertyNames( Animal.prototype )
// [ 'constructor', 'getAnimalType' ]

回答by goofballLogic

i know, i know, but hey...

我知道,我知道,但是嘿...

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 userFunctions = x => distinctDeepFunctions( x ).filter( name => name !== "constructor" && !~name.indexOf( "__" ) );


// example usage

class YourObject {   
   hello() { return "uk"; }
   goodbye() { return "eu"; }
}

class MyObject extends YourObject {
   hello() { return "ie"; }
   get when() { return "soon"; } 
}

const obj = new MyObject();
console.log( userFunctions( obj ) ); // [ "hello", "when", "goodbye" ]

回答by Pavel Ye

Since methods on ES6 class are non-enumerable, you have no other option but to use Object.getOwnPropertyNames()to get an array of all its properties.

由于 ES6 类上的方法是不可枚举的,因此您别无选择,只能使用Object.getOwnPropertyNames()来获取其所有属性的数组。

After achieving that, there are several ways to go about extracting methods, the simplest of which might be using Array.prototype.forEach().

实现这一点后,有几种方法可以提取方法,其中最简单的方法可能是使用Array.prototype.forEach()

Check out the following snippet:

查看以下代码段:

Object.getOwnPropertyNames(Animal.prototype).forEach((value) => {
    console.log(value);
})

回答by Basav

Try this one liner way, if you need just the functions (like replacement to _.functions)

如果您只需要函数(例如替换_.functions),请尝试这种线性方式

function getInstanceMethodNames (obj) {
    return Object
        .getOwnPropertyNames (Object.getPrototypeOf (obj))
        .filter(name => (name !== 'constructor' && typeof obj[name] === 'function'));
}

回答by Yago Lopez

For anyone using Typescript interested in this kind of questions you can do a lot of things in a simple way using metadata-reflection api. For example you can add metadata to your classes using decorators and get information about class methods, properties and their types. Typescript and its types allows to do similar things to compiled languages like java, c# and their introspection apis.

对于任何对此类问题感兴趣的使用 Typescript 的人,您都可以使用元数据反射 api 以简单的方式做很多事情。例如,您可以使用装饰器向类添加元数据,并获取有关类方法、属性及其类型的信息。Typescript 及其类型允许对编译语言(如 java、c# 及其自省 api)执行类似的操作。

Take a look to these links for more info:

查看这些链接以获取更多信息:

https://www.typescriptlang.org/docs/handbook/decorators.html

https://www.typescriptlang.org/docs/handbook/decorators.html

https://www.npmjs.com/search?q=reflect-metadata

https://www.npmjs.com/search?q=reflect-metadata

回答by Leo Dutra

This is a bit more elaborated but gets methods from the whole prototype chain.

这有点复杂,但从整个原型链中获取方法。

function getAllMethodNames (obj, depth = Infinity) {
    const methods = new Set()
    while (depth-- && obj) {
        for (const key of Reflect.ownKeys(obj)) {
            methods.add(key)
        }
        obj = Reflect.getPrototypeOf(obj)
    }
    return [...methods]
}

回答by haouarin

This is an enhanced version of the answer suggested here https://stackoverflow.com/a/35033472/3811640

这是此处建议的答案的增强版本https://stackoverflow.com/a/35033472/3811640

I add the parameter deep, deep= Infinity by default to extract all the functions including parent functions. deep =1 to extract the direct methods of a given class.

我默认添加参数 deep, deep= Infinity 以提取包括父函数在内的所有函数。deep =1 提取给定类的直接方法。

getAllMethods = function (obj, deep = Infinity) {
    let props = []

    while (
      (obj = Object.getPrototypeOf(obj)) && // walk-up the prototype chain
      Object.getPrototypeOf(obj) && // not the the Object prototype methods (hasOwnProperty, etc...)
      deep !== 0
    ) {
      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)
      deep--
    }

    return props
  }
  

class Foo {
  
  method01 (){
  }
  
  method02 (){
  }
  
  }
  
  
  class FooChield extends Foo {
  
  method01(){
  }
  
  method03(){
  }
  } 
  

  
  console.log('All methods', getAllMethods(new FooChield())) 
  
  console.log('Direct methods', getAllMethods(new FooChield(),1))

enter code here

回答by Ponmudi VN

check this fiddle

检查这个小提琴

https://jsfiddle.net/ponmudi/tqmya6ok/1/

https://jsfiddle.net/ponmudi/tqmya6ok/1/

class Animal {
    constructor(type){
        this.animalType = type;
    }
    getAnimalType(){
        console.log('this.animalType: ', this.animalType );
    }
}

let cat = new Animal('cat');

//by instance
document.getElementById('1').innerHTML = Object.getOwnPropertyNames(cat);

//by getting prototype from instance
document.getElementById('2').innerHTML = Object.getOwnPropertyNames(Object.getPrototypeOf(cat));

//by prototype
document.getElementById('3').innerHTML = Object.getOwnPropertyNames(Animal.prototype);

回答by Jules

If you need to get superclass methods as well, you can call Object.getPrototypeOf()repeatedly until you find them all. You'll probably want to stop when you get to Object.prototype, because the methods in there are fundamental and you usually don't want to touch them with any code that uses reflection.

如果还需要获取超类方法,则可以Object.getPrototypeOf()重复调用,直到找到所有方法为止。当您到达 时,您可能想要停下来Object.prototype,因为那里的方法是基本的,您通常不想用任何使用反射的代码来触及它们。

The question Get functions (methods) of a classhas an answer that includes a function for doing this, but it had a few shortcomings (including using a loop condition which had a side effect of modifying a function argument, which I figure makes two questionable code style choices in a single line of code...), so I've rewritten it here:

类的获取函数(方法)问题的答案包括用于执行此操作的函数,但它有一些缺点(包括使用具有修改函数参数的副作用的循环条件,我认为这使两个问题单行代码中的代码样式选择...),所以我在这里重写了它:

export function listMethodNames (object, downToClass = Object)
{
    // based on code by Muhammad Umer, https://stackoverflow.com/a/31055217/441899
    let props = [];

    for (let obj = object; obj !== null && obj !== downToClass.prototype; obj = Object.getPrototypeOf(obj))
    {
        props = props.concat(Object.getOwnPropertyNames(obj));
    }

    return props.sort().filter((e, i, arr) => e != arr[i+1] && typeof object[e] == 'function');
}

As well as fixing the bug in the original code (which didn't copy the object into another variable for the loop, so by the time it was used for filtering in the return line it was no longer valid) this gives an optional argument to stop the iteration at a configurable class. It'll default to Object(so Object's methods are excluded; if you want to include them you can use a class that doesn't appear in the inheritance chain... perhaps making a marker class e.g. class IncludeObjectMethods{}might make sense). I've also changed the doloop to a clearer forloop and rewritten the old-style function ...filter function into an ES6 arrow function to make the code more compact.

以及修复原始代码中的错误(它没有将对象复制到循环的另一个变量中,因此当它用于在返回行中进行过滤时它不再有效)这给出了一个可选参数在可配置的类处停止迭代。它将默认为Object(soObject的方法被排除在外;如果你想包含它们,你可以使用一个没有出现在继承链中的类......也许制作一个标记类,例如class IncludeObjectMethods{}可能有意义)。我还将do循环更改为更清晰的for循环,并将旧式function ...过滤器函数重写为 ES6 箭头函数,以使代码更加紧凑。