javascript - objetos - Forma correcta de agregar funciones dinĂ¡micamente a las clases ES6
objetos en javascript (3)
Me gusta la respuesta de @leonid, pero ¿hay alguna manera de permitir que se produzcan destrozos cuando se usan nombres de propiedades computados dinámicos?
[''VERYBIGNAME'', ''VERYBIGNAME2'', ''VERYBIGNAME3''].forEach((method) => {
Executor.prototype[method] = function (body) {
return this.request(method, body)
}
})
en su javascript minificado y destrozado existirán estas cadenas VERYBIGNAME.
así que si puedo obtener referencias a estas funciones de VERYBIGNAME puedo usar algo como
const references = { VERYBIGNAME1, VERYBIGNAME2, VERYBIGNAME3 };
Object.assign(Executor.prototype, { ...references });
Tengo una clase simple con un solo método exec(arg1,..,argn)
y quiero tener una serie de métodos de alias que llamen a exec
con valores de argumento predefinidos (por ejemplo, exec_sync = exec.bind(this, true)
).
Lo siguiente hace el truco:
class Executor {
constructor() {
this.exec_sync = this.exec.bind(this, true);
}
exec(sync, cmd, args/* ... */) {
// impl
}
}
Pero no sé si es una buena idea o si es idiomática para ES6.
UDATE:
En un ejemplo de la vida real tengo dos bucles anidados con 3 y 4 bucles respectivamente, que se usan para agregar dinámicamente un número total de 12 métodos de alias a la clase. Sería una tarea incómoda definir explícitamente los métodos de alias cuando realmente puede aprovechar que JS es un lenguaje de programación basado en prototipos.
ACTUALIZACIÓN 2 - EJEMPLO:
Supongamos que tenemos un cliente HTTP simple con una request(method, body)
método request(method, body)
y queremos proporcionar métodos de alias para GET
, PUT
, etc. Se vería algo como lo siguiente:
class HTTP {
constructor() {
[''GET'', ''PUT'', ''POST'', ''DEL''].forEach((method) => {
this[method] = this.request.bind(this, method);
}, this);
}
request(method, body) {
// execute the HTTP request
}
}
No sé si esto es idiomático (ya que se trata más de diseño que de lenguaje de programación), pero personalmente creo que sería mejor crear funciones explícitas:
exec_sync(...args) {
return this.exec(true, ...args);
}
Su solución está bien, aunque será mejor crear todos esos métodos una vez en un nivel de prototype
:
[''GET'', ''PUT'', ''POST'', ''DEL''].forEach((method) => {
Executor.prototype[method] = function (body) {
return this.request(method, body)
}
})
prototype
enfoque de prototype
es ligeramente más rápido, porque este código se ejecuta solo una vez, mientras que el código del constructor se ejecuta cada vez que se crea una nueva instancia.
Otra ventaja del prototype
sobre el constructor
es que es compatible con la herencia de clases. Entonces, si extiendes tu clase más tarde, nada se romperá incluso si redefinirás cualquiera de esos métodos.
Por cierto, puede usar require(''http'').METHODS
o los paquetes de methods
lugar de la matriz codificada de verbos HTTP aquí.