Javascript ES6迭代类方法

Javascript ES6迭代类方法,javascript,ecmascript-6,Javascript,Ecmascript 6,鉴于这一类;我将如何迭代它包含的方法 class Animal { constructor(type){ this.animalType = type; } getAnimalType(){ console.log('this.animalType: ', this.animalType ); } } let cat = window.cat = new Animal('cat') 我尝试了以下方法,但没有成功: for (va

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

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

let cat = window.cat = new Animal('cat')
我尝试了以下方法,但没有成功:

for (var each in Object.getPrototypeOf(cat) ){
    console.log(each);
}
您可以在原型上使用:

Object.getOwnPropertyNames( Animal.prototype )
// [ 'constructor', 'getAnimalType' ]
您可以在原型上使用:

Object.getOwnPropertyNames( Animal.prototype )
// [ 'constructor', 'getAnimalType' ]
检查这把小提琴

检查这把小提琴


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

这个问题有一个答案,其中包含了一个函数来实现这一点,但它有一些缺点(包括使用循环条件,这会产生修改函数参数的副作用,我认为这会在一行代码中做出两个有问题的代码样式选择…),所以我在这里重写了它:

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');
}

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

如果您还需要获得超类方法,您可以反复调用
Object.getPrototypeOf()
,直到找到它们为止。当您到达
Object.prototype
时,您可能会想停止,因为其中的方法是基本的,您通常不想用任何使用反射的代码来触碰它们

这个问题有一个答案,其中包含了一个函数来实现这一点,但它有一些缺点(包括使用循环条件,这会产生修改函数参数的副作用,我认为这会在一行代码中做出两个有问题的代码样式选择…),所以我在这里重写了它:

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');
}

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

由于ES6类上的方法是不可枚举的,因此除了获取其所有属性的数组之外,您别无选择

在实现这一点之后,有几种方法可以提取方法,其中最简单的可能是使用

查看以下代码段:

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

由于ES6类上的方法是不可枚举的,所以除了获取其所有属性的数组之外,您别无选择

在实现这一点之后,有几种方法可以提取方法,其中最简单的可能是使用

查看以下代码段:

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

我知道,我知道,但是嘿

const isGetter=(x,name)=>(Object.getOwnPropertyDescriptor(x,name)|{})。获取
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(新集合(deepFunctions(x));
const userFunctions=x=>distinctDeepFunctions(x).filter(name=>name!==“constructor”&&!~name.indexOf(“\uuuxof”);
//示例用法
类对象{
hello(){返回“uk”;}
再见(){返回“eu”;}
}
类MyObject扩展了YourObject{
hello(){return“ie”;}
获取时间(){return“soon”;}
}
const obj=新的MyObject();

console.log(userFunctions(obj));//[“你好”、“什么时候”、“再见”]
我知道,我知道,但是嘿

const isGetter=(x,name)=>(Object.getOwnPropertyDescriptor(x,name)|{})。获取
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(新集合(deepFunctions(x));
const userFunctions=x=>distinctDeepFunctions(x).filter(name=>name!==“constructor”&&!~name.indexOf(“\uuuxof”);
//示例用法
类对象{
hello(){返回“uk”;}
再见(){返回“eu”;}
}
类MyObject扩展了YourObject{
hello(){return“ie”;}
获取时间(){return“soon”;}
}
const obj=新的MyObject();

console.log(userFunctions(obj));//[“你好”、“什么时候”、“再见”]
对于任何使用Typescript对此类问题感兴趣的人,您可以使用元数据反射api以一种简单的方式完成很多事情。例如,您可以使用装饰器向类添加元数据,并获取有关类方法、属性及其类型的信息。Typescript及其类型允许对java、c#及其自省API等编译语言执行类似的操作
var getMethods = function(obj) {
    const o = Reflect.getPrototypeOf(obj);
    const x = Reflect.getPrototypeOf(o);
    return Reflect.ownKeys(o).filter(it => Reflect.ownKeys(x).indexOf(it) < 0);
}