2015-09-10 13 views
13

Mam prostą klasę z jedną metodą exec(arg1,..,argn) i chcę mieć wiele metod aliasowych, które wywołują exec z predefiniowanymi wartościami argumentów (np. exec_sync = exec.bind(this, true)).Właściwy sposób dynamicznego dodawania funkcji do klas ES6

Poniższa załatwia sprawę:

class Executor { 
    constructor() { 
    this.exec_sync = this.exec.bind(this, true); 
    } 

    exec(sync, cmd, args/* ... */) { 
    // impl 
    } 
} 

Ale ja nie wiem, czy to jest dobry pomysł, czy to jest idiomatyczne do ES6.

UDATE:

W rzeczywistych przykładem dwie zagnieżdżone pętle z odpowiednio 3 i 4, pętle, które są stosowane w celu dynamicznego dodać całkowitą liczbę 12 alias metod do klasy. Uciążliwym zadaniem byłoby jawne zdefiniowanie metod aliasów, gdy faktycznie można skorzystać z JS, który jest językiem programowania opartym na prototypach.

UPDATE 2 - PRZYKŁAD:

Załóżmy, że mamy mieć prosty klient HTTP z metody request(method, body) i chcemy zapewnić metody alias GET, PUT itp Byłoby to wyglądać mniej więcej tak:

class HTTP { 
    constructor() { 
    ['GET', 'PUT', 'POST', 'DEL'].forEach((method) => { 
     this[method] = this.request.bind(this, method); 
    }, this); 
    } 

    request(method, body) { 
    // execute the HTTP request 
    } 
} 
+0

Dlaczego nie tworzyć jawnie wielu funkcji? 'exec_sync (... args) {return this.exec (true, ... args); } ' – zerkms

+0

@zerkms Myślę, że byłoby bardziej jasne, co robi klasa. Po prostu interesowała mnie możliwość zrobienia czegoś takiego. –

+0

Klasy ES6 to po prostu cukier syntaktyczny. Nic nie zmieniło się pod względem dodawania właściwości do obiektu w środowisku wykonawczym. –

Odpowiedz

19

Twoje rozwiązanie jest w porządku, chociaż to będzie lepiej, aby utworzyć wszystkie te metody raz na prototype poziomie:

['GET', 'PUT', 'POST', 'DEL'].forEach((method) => { 
    Executor.prototype[method] = function (body) { 
    return this.request(method, body) 
    } 
}) 

prototype podejście jest nieco szybsza, ponieważ ten kod jest wykonywany tylko raz, podczas gdy Kod konstruktora jest wykonywany za każdym razem, gdy tworzona jest nowa instancja.

Kolejną zaletą prototype w stosunku do constructor jest zgodność z dziedziczeniem klas. Jeśli więc rozszerzysz swoją klasę później, nic się nie złamie, nawet jeśli zredefiniujesz którąś z tych metod.

Przy okazji, można zamiast tego używać niezmiennych tablic HTTP verbs tutaj: require('http').METHODS lub methods package.

+0

Dzięki. http rzeczy powinny być przykładem, nie używam go w moim kodzie :) –

+0

Pozwól nam [kontynuować tę dyskusję na czacie] (http://chat.stackoverflow.com/rooms/89272/discussion-between-yan -foto-and-leonid-beschastny). –

+0

Wiele ES5 bardzo wow, gdzie jest mój sposób ES6? –

1

nie wiem, o co jest idiomatyczne (ponieważ jest to więcej o projektowaniu, a nie sam język programowania), ale osobiście uważam, tworząc wyraźne funkcje byłoby lepiej:

exec_sync(...args) { 
    return this.exec(true, ...args); 
} 
+0

W prawdziwym przykładzie mam 2 zagnieżdżone pętle, które odpowiednio mają 3 i 4 elementy używane do dynamicznego dodawania w sumie 12 elementów do klasy. byłoby trochę uciążliwe, aby dodać wszystko ręcznie. –

+0

@Yanobraz Myślę o przeniesieniu go do osobnej klasy w rzeczywistości. – zerkms

+0

Te metody faktycznie i semantycznie należą do klasy. Jeśli przeniesię je do oddzielnej klasy, nadal będę musiał je zdefiniować jawnie. czy coś tu mi brakuje? –

Powiązane problemy