获取类的函数(方法)

时间:2015-06-25 15:41:55

标签: javascript oop ecmascript-6

我必须动态获取ES6类的属性和功能。这甚至可能吗?

使用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);
}

输出:

bar

5 个答案:

答案 0 :(得分:40)

班级的成员不可枚举。要获得它们,您必须使用Object.getOwnPropertyNames

var propertyNames = Object.getOwnPropertyNames(Object.getPrototypeOf(foo));
// or
var propertyNames = Object.getOwnPropertyNames(Foo.prototype);

当然这不会得到继承的方法。没有任何方法可以为您提供所有这些方法。您必须遍历原型链并单独获取每个原型的属性。

答案 1 :(得分:37)

此功能将获得所有功能。是继承与否,可枚举与否。包括所有功能。

File file = new File(path);
Picasso.with(context).load(file).placeholder(placeholderResId).into(imageView);

进行测试

function getAllFuncs(obj) { var props = []; 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 obj[e] == 'function') return true; }); }

控制台输出:

getAllFuncs([1,3]);

注意

它不返回通过符号定义的函数;

答案 2 :(得分:18)

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]);




答案 3 :(得分:8)

@MuhammadUmer在我的回答中有一些问题(符号,索引i+1Object方法列表等等......)所以从中获取灵感,我想出了这个< / p>

(警告编写到ES6的Typescript)

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
}

此函数将列出该类实例的所有方法,包括那些继承的构造函数和Object原型的那些。

测试

该函数返回

[ 'asyncMethod',
  'echo',
  'generatorMethod',
  'ping',
  'pong',
  'anotherEcho' ]

列出TestClass(typescript)

实例的方法
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'
    }
}

答案 4 :(得分:2)

要使类成员可枚举,您可以使用Symbol.iterator

我必须得到所有允许的对象方法(包括继承)。所以我创建了课程&#34; Enumerable&#34;以及我继承的所有基类。

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