鉴于此课程;我将如何迭代它包含的方法?
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);
}
答案 0 :(得分:54)
您可以在原型上使用Object.getOwnPropertyNames:
Object.getOwnPropertyNames( Animal.prototype )
// [ 'constructor', 'getAnimalType' ]
答案 1 :(得分:11)
我知道,我知道,但是嘿......
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" ]

答案 2 :(得分:2)
由于ES6类上的方法是不可枚举的,因此您没有其他选择,只能使用Object.getOwnPropertyNames()来获取其所有属性的数组。
实现这一目标后,有几种方法可以提取方法,其中最简单的方法可能是使用Array.prototype.forEach()。
查看以下代码段:
Object.getOwnPropertyNames(Animal.prototype).forEach((value) => {
console.log(value);
})
答案 3 :(得分:1)
这有点复杂,但是可以从整个原型链中获取方法。
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]
}
答案 4 :(得分:0)
检查这个小提琴
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);
答案 5 :(得分:0)
如果您还需要获取超类方法,可以反复调用Object.getPrototypeOf()
,直到找到所有方法。当你到达Object.prototype
时,你可能想要停下来,因为那里的方法很基础,你通常不想用任何使用反射的代码触摸它们。
问题Get functions (methods) of a class有一个答案,其中包含一个执行此操作的函数,但它有一些缺点(包括使用一个循环条件,它具有修改函数参数的副作用,我认为这有两个问题代码样式选择在一行代码中...),所以我在这里重写了它:
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
循环,并将旧式function ...
过滤器函数重写为ES6箭头函数,以使代码更紧凑。
答案 6 :(得分:0)
对于使用对此类问题感兴趣的Typescript的任何人,您可以使用元数据反射API以简单的方式执行许多操作。例如,您可以使用装饰器向类添加元数据,并获取有关类方法,属性及其类型的信息。 Typescript及其类型允许对编译语言(如java,c#和它们的内省apis)执行类似的操作。
请查看这些链接以获取更多信息:
https://www.typescriptlang.org/docs/handbook/decorators.html
答案 7 :(得分:0)
如果仅需要功能(例如替换为_.functions),请尝试这种单线方式
function getInstanceMethodNames (obj) {
return Object
.getOwnPropertyNames (Object.getPrototypeOf (obj))
.filter(name => (name !== 'constructor' && typeof obj[name] === 'function'));
}
答案 8 :(得分:0)
这是此处https://stackoverflow.com/a/35033472/3811640
建议的答案的增强版本。默认情况下,我添加参数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
答案 9 :(得分:0)
另一种无需列出构造函数和其他属性即可获取它们的方法:
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);
}
答案 10 :(得分:0)
为什么这里的答案如此复杂?让我们简单点。
Object.getOwnPropertyNames(...)
是获取非继承类方法名称的标准且唯一的方法。 [按字母顺序作为数组返回]
Object.getPrototypeOf(...)
是获取继承原型的标准且唯一的方法。 [作为 Class.prototype 返回]
所以,只是循环
Object.getPrototypeOf(Object.getPrototypeOf(
Object.getPrototypeOf( Object.getPrototypeOf(
...
Object.getPrototypeOf( your_object )
...
))
))
直到它的构造函数 === Object
// JavaScript
class A {
myWife() { console.log(4) }
}
class B extends A {
myParent() { console.log(5) }
}
class C extends B {
myBrother() { console.log(6) }
}
class D extends C {
mySelf() { console.log(7) }
}
let obj = new D;
function classMethodsA(obj) {
let res = {};
let p = Object.getPrototypeOf(obj)
while (p.constructor !== Object) {
for(const k of Object.getOwnPropertyNames(p)){
if (!(k in res)) res[k] = obj[k];
}
p = Object.getPrototypeOf(p)
}
return res;
}
function classMethodsB(obj) {
let res = [];
let p = Object.getPrototypeOf(obj);
while (p.constructor !== Object) {
for(const k of Object.getOwnPropertyNames(p)){
if (!res.includes(k)) res.push(k);
}
p = Object.getPrototypeOf(p);
}
return res;
}
document.body.innerHTML=`
<p> -- No Constructor -- ${Object.keys(classMethodsA(obj))}</p>
<p> -- With Constructor -- ${classMethodsB(obj)}</p>
`;