Encuentro la función de parámetros nombrados en C # bastante útil en algunos casos.
calculateBMI(70, height: 175);
¿Qué puedo usar si quiero esto en JavaScript?
Lo que no quiero es esto:
myFunction({ param1: 70, param2: 175 });
function myFunction(params){
// Check if params is an object
// Check if the parameters I need are non-null
// Blah blah
}
Ese enfoque ya lo he usado. ¿Hay otra manera?
Estoy bien usando cualquier biblioteca para hacer esto.
javascript
function
optional-parameters
named-parameters
Robin Maben
fuente
fuente
Function
puede hacer el JavaScript existente .Function
en Javascript no puede cambiar la sintaxis central de JavascriptcalculateBMI(70, /*height:*/ 175);
, (2) proporcionar un objetocalculateBMI(70, {height: 175})
o (3) usar una constanteconst height = 175; calculateBMI(70, height);
.Respuestas:
ES2015 y posterior
En ES2015, la desestructuración de parámetros se puede utilizar para simular parámetros con nombre. Requeriría que la persona que llama pasara un objeto, pero puede evitar todas las comprobaciones dentro de la función si también utiliza parámetros predeterminados:
ES5
Hay una manera de acercarse a lo que desea, pero se basa en la salida de
Function.prototype.toString
[ES5] , que depende en cierta medida de la implementación, por lo que podría no ser compatible con varios navegadores.La idea es analizar los nombres de los parámetros de la representación de cadena de la función para que pueda asociar las propiedades de un objeto con el parámetro correspondiente.
Una llamada a la función podría verse así
donde
a
yb
son argumentos posicionales y el último argumento es un objeto con argumentos nombrados.Por ejemplo:
Que usarías como:
MANIFESTACIÓN
Hay algunos inconvenientes en este enfoque (¡ya te lo advertimos!):
undefined
(eso es diferente de no tener ningún valor). Eso significa que no puede usararguments.length
para probar cuántos argumentos se han pasado.En lugar de tener una función que cree el contenedor, también podría tener una función que acepte una función y varios valores como argumentos, como
o incluso extender
Function.prototype
para que puedas hacer:fuente
Object.defineProperty
y conjuntoenumerable
afalse
). Siempre se debe tener cuidado al extender objetos nativos. Todo el enfoque se siente un poco extraño, por lo que no esperaría que funcione ahora y para siempre;)undefined
vs "sin valor", se puede agregar que así es exactamente como funcionan los valores predeterminados de las funciones de JS, tratandoundefined
como un valor perdido.No , el enfoque de objeto es la respuesta de JavaScript a esto. No hay ningún problema con esto, siempre que su función espere un objeto en lugar de parámetros separados.
fuente
Este problema ha sido una manía mía desde hace algún tiempo. Soy un programador experimentado con muchos idiomas en mi haber. Uno de mis idiomas favoritos que he tenido el placer de usar es Python. Python admite parámetros con nombre sin ningún truco ... Desde que comencé a usar Python (hace algún tiempo) todo se volvió más fácil. Creo que cada idioma debe admitir parámetros con nombre, pero ese no es el caso.
Mucha gente dice que use el truco "Pasar un objeto" para que haya nombrado los parámetros.
Y eso funciona muy bien, excepto ... cuando se trata de la mayoría de los IDE, muchos de nosotros los desarrolladores confiamos en sugerencias de tipo / argumento dentro de nuestro IDE. Yo personalmente uso PHP Storm (junto con otros IDE de JetBrains como PyCharm para python y AppCode para Objective C)
Y el mayor problema con el uso del truco "Pasar un objeto" es que cuando se llama a la función, el IDE le da una pista de tipo único y eso es todo ... ¿Cómo se supone que debemos saber qué parámetros y tipos deben entrar en el objeto arg1?
Entonces ... el truco "Pasar un objeto" no funciona para mí ... En realidad, causa más dolores de cabeza al tener que mirar el bloque de documentos de cada función antes de saber qué parámetros espera la función ... Claro, es genial para cuando mantiene el código existente, pero es horrible para escribir código nuevo.
Bueno, esta es la técnica que uso ... Ahora, puede haber algunos problemas con ella, y algunos desarrolladores pueden decirme que lo estoy haciendo mal, y tengo una mente abierta cuando se trata de estas cosas ... Siempre estoy dispuesto a buscar mejores formas de lograr una tarea ... Entonces, si hay un problema con esta técnica, entonces los comentarios son bienvenidos.
De esta manera, tengo lo mejor de ambos mundos ... el nuevo código es fácil de escribir ya que mi IDE me da todas las sugerencias de argumento adecuadas ... Y, mientras mantengo el código más adelante, puedo ver de un vistazo, no solo el valor pasado a la función, pero también el nombre del argumento. La única sobrecarga que veo es declarar los nombres de sus argumentos como variables locales para evitar contaminar el espacio de nombres global. Claro, es un poco de tipeo adicional, pero trivial en comparación con el tiempo que lleva buscar docblocks mientras escribe un código nuevo o mantiene el código existente.
fuente
myFunc(/*arg1*/ 'Param1', /*arg2*/ 'Param2');
es mejor quemyFunc(arg1='Param1', arg2='Param2');
eso, porque eso no tiene ninguna posibilidad de engañar al lector que cualquier argumento con nombre real está sucediendoSi desea dejar en claro cuáles son cada uno de los parámetros, en lugar de simplemente llamar
por qué no hacer lo siguiente
claro, es una línea de código extra, pero gana en legibilidad.
fuente
someFunction(height: 115);
pero si escribesomeFunction(height);
, en realidad está estableciendo el ancho.someFunction(width = 70, height = 115);
. Las variables se declaran en la parte superior del alcance actual en el código JavaScript que se genera.Otra forma sería utilizar los atributos de un objeto adecuado, por ejemplo, así:
Por supuesto, para este ejemplo inventado es algo sin sentido. Pero en casos donde la función se ve como
Podría ser más útil. También podría combinarse con la idea de "parameterfy" para crear dicho objeto a partir de una función existente de forma genérica. Es decir, para cada parámetro crearía un miembro que puede evaluar una versión parcial evaluada de la función.
Esta idea, por supuesto, está relacionada con Schönfinkeling, también conocido como Curry.
fuente
Hay otra manera Si pasa un objeto por referencia, las propiedades de ese objeto aparecerán en el ámbito local de la función. Sé que esto funciona para Safari (no he comprobado otros navegadores) y no sé si esta característica tiene un nombre, pero el siguiente ejemplo ilustra su uso.
Aunque en la práctica no creo que esto ofrezca ningún valor funcional más allá de la técnica que ya está utilizando, es un poco más limpio semánticamente. Y todavía requiere pasar una referencia de objeto o un literal de objeto.
fuente
Al probar Node-6.4.0 (process.versions.v8 = '5.0.71.60') y Node Chakracore-v7.0.0-pre8 y luego Chrome-52 (V8 = 5.2.361.49), noté que los parámetros con nombre son casi implementado, pero ese orden todavía tiene precedencia. No puedo encontrar lo que dice el estándar ECMA.
¡Pero se requiere orden! ¿Es el comportamiento estándar?
fuente
b=10
expresión es10
, y eso es lo que se pasa a la función.f(bla=10)
también funcionaría (asigna 10 a la variablebla
y luego pasa el valor a la función).a
yb
variables en el ámbito global como un efecto secundario.Función
f
de llamada con parámetros con nombre pasados como objetobásicamente está llamando a su composición
f(...g(o))
donde estoy usando la sintaxis de propagación yg
es un mapa "vinculante" que conecta los valores de los objetos con sus posiciones de parámetros.El mapa de enlace es precisamente el ingrediente que falta, que puede representarse por la matriz de sus claves:
Tenga en cuenta los tres ingredientes desacoplados: la función, el objeto con argumentos con nombre y el enlace. Este desacoplamiento permite mucha flexibilidad para usar esta construcción, donde el enlace puede personalizarse arbitrariamente en la definición de la función y ampliarse arbitrariamente en el momento de la llamada a la función.
Por ejemplo, es posible que desee abreviar
height
ywidth
comoh
yw
dentro de la definición de su función, para que sea más corta y limpia, mientras que aún desea llamarlo con nombres completos para mayor claridad:Esta flexibilidad también es más útil para la programación funcional, donde las funciones pueden transformarse arbitrariamente con la pérdida de sus nombres de parámetros originales.
fuente
Viniendo de Python esto me molestó. Escribí un contenedor / Proxy simple para el nodo que aceptará objetos posicionales y de palabras clave.
https://github.com/vinces1979/node-def/blob/master/README.md
fuente
f(x, opt)
dóndeopt
está un objeto? Si ayuda a evitar o crear errores (como los causados por errores ortográficos y el dolor de recordar nombres de palabras clave) sigue siendo una pregunta.kwargs
dict, una por una, y finalmente levantaría unaTypeError
si las claves desconocidas se quedan). Suf(x, opt)
solución permite que laf
función haga algo como en Python 2, pero necesitaría manejar todos los valores predeterminados usted mismo.f(x, opt)
ya está funcionando, aunque no veo cómo esto ayuda a responder la pregunta, por ejemplo, dónde quiere hacer ambas cosasrequest(url)
yrequest({url: url})
eso no sería posible al hacerurl
un parámetro de solo palabras clave.Al contrario de lo que comúnmente se cree, los parámetros con nombre pueden implementarse en JavaScript estándar de la vieja escuela (solo para parámetros booleanos) mediante una convención de codificación simple y ordenada, como se muestra a continuación.
Advertencias:
Se debe preservar el orden de los argumentos, pero el patrón sigue siendo útil, ya que deja en claro qué argumento real se entiende para qué parámetro formal sin tener que buscar la firma de la función o usar un IDE.
Esto solo funciona para booleanos. Sin embargo, estoy seguro de que se podría desarrollar un patrón similar para otros tipos utilizando la semántica de coerción de tipos única de JavaScript.
fuente
height
por nombre independientemente de la orden param.