2015-06-17 2 views
23

С учетом этого класса; как бы я перебирал методы, которые он включает?ES6 Итерация над методами класса

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); 
} 
+1

Если не итерация 'животных .prototype' работа? Из того, что я понимаю, базовая архитектура объекта по-прежнему совпадает с «старым» способом. – slebetman

+0

Animal.prototype раскрывает методы. Я думаю, что проблема заключается в том, чтобы перебирать их. для .. in, похоже, не работает. – seasick

ответ

39

Вы можете использовать Object.getOwnPropertyNames на прототипе:

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

Я не пробовал это - но будет ли это работать над чем-то, что унаследовано? Я не уверен, что это будет ... и только для суперкласса. – seasick

+2

@seasick Это работает, но вам нужно будет использовать 'Object.getPrototypeOf', чтобы сначала перейти к прототипу: 'Object.getOwnPropertyNames (Object.getPrototypeOf (cat))' – Paulpro

+0

Спасибо !!!! Это определенно работает, но учитывая синтаксис всего этого. Интересно, является ли это предпочтительным способом сделать что-то подобное. То, что мне нужно, - это просто называть все методы класса, но не хочу делать это в буквальном типе, поэтому я хотел итерации через них. – seasick

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); 
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, чтобы сделать код более компактным.

2

Поскольку методы класса ES6 неперечислимы, у вас нет другого варианта, кроме как использовать Object.getOwnPropertyNames() для получения массива всех его свойств.

После достижения этого существует несколько способов использования методов извлечения, самым простым из которых может быть использование Array.prototype.forEach().

Заканчивать следующий фрагмент:

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

я знаю, я знаю, но эй ...

const deepProps = x => x && x !== Object.prototype && Object.getOwnPropertyNames(x).concat(deepProps(Object.getPrototypeOf(x)) || []); 
const deepFunctions = x => deepProps(x).filter(name => typeof x[ name ] === "function"); 
const userFunctions = x => new Set(deepFunctions(x).filter(name => name !== "constructor" && !~name.indexOf("__"))); 

использование:

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

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

const x = new MyObject(); 
userFunctions(x); // [ "hello", "goodbye" ] 
+0

Должен быть выбранный ответ, он работает как для ES6, так и для динамического объекта и наследования ES6. – ktutnik

Смежные вопросы