Al crear una función de JavaScript con múltiples argumentos, siempre me enfrento a esta opción: pasar una lista de argumentos frente a pasar un objeto de opciones.
Por ejemplo, estoy escribiendo una función para asignar una lista de nodos a una matriz:
function map(nodeList, callback, thisObject, fromIndex, toIndex){
...
}
En cambio, podría usar esto:
function map(options){
...
}
donde options es un objeto:
options={
nodeList:...,
callback:...,
thisObject:...,
fromIndex:...,
toIndex:...
}
¿Cuál es la forma recomendada? ¿Existen pautas sobre cuándo usar uno versus el otro?
[Actualización] Parece haber un consenso a favor del objeto de opciones, por lo que me gustaría agregar un comentario: una razón por la que me sentí tentado a usar la lista de argumentos en mi caso fue tener un comportamiento coherente con el JavaScript construido en el método array.map.
Array.prototype.map
tiene una API simple que no debería dejar a ningún codificador semi-experimentado desconcertado.Respuestas:
Como muchos de los otros, a menudo prefiero pasar un
options object
a una función en lugar de pasar una larga lista de parámetros, pero realmente depende del contexto exacto.Utilizo la legibilidad del código como prueba de fuego.
Por ejemplo, si tengo esta función, llame a:
Creo que el código es bastante legible tal como está y pasar parámetros individuales está bien.
Por otro lado, hay funciones con llamadas como esta:
Completamente ilegible a menos que investigue un poco. Por otro lado, este código se lee bien:
Es más un arte que una ciencia, pero si tuviera que nombrar reglas generales:
Use un parámetro de opciones si:
fuente
Los argumentos múltiples son principalmente para parámetros obligatorios. No hay nada malo con ellos.
Si tiene parámetros opcionales, se complica. Si uno de ellos se basa en los demás, para que tengan un cierto orden (por ejemplo, el cuarto necesita el tercero), aún debe usar múltiples argumentos. Casi todos los métodos nativos de EcmaScript y DOM funcionan así. Un buen ejemplo es el
open
método de solicitudes XMLHTTP , donde los últimos 3 argumentos son opcionales: la regla es como "sin contraseña sin un usuario" (consulte también los documentos MDN ).Los objetos opcionales son útiles en dos casos:
undefined
.En su caso, lo recomendaría
map(nodeList, callback, options)
.nodelist
ycallback
son obligatorios, los otros tres argumentos se presentan solo ocasionalmente y tienen valores predeterminados razonables.Otro ejemplo es
JSON.stringify
. Es posible que desee utilizar elspace
parámetro sin pasar unareplacer
función; luego debe llamar…, null, 4)
. Un objeto de argumentos podría haber sido mejor, aunque no es realmente razonable para solo 2 parámetros.fuente
Usar el enfoque de 'opciones como objeto' será lo mejor. No tiene que preocuparse por el orden de las propiedades y hay más flexibilidad en los datos que se pasan (parámetros opcionales, por ejemplo)
Crear un objeto también significa que las opciones podrían usarse fácilmente en múltiples funciones:
fuente
Creo que si está creando una instancia de algo o llamando a un método de un objeto, desea utilizar un objeto de opciones. Si es una función que opera en uno o dos parámetros y devuelve un valor, es preferible una lista de argumentos.
En algunos casos, es bueno usar ambos. Si su función tiene uno o dos parámetros obligatorios y varios opcionales, haga que los dos primeros parámetros sean obligatorios y el tercero un hash de opciones opcional.
En tu ejemplo, lo haría
map(nodeList, callback, options)
. Nodelist y callback son obligatorios, es bastante fácil saber lo que sucede con solo leer una llamada, y es como las funciones de mapa existentes. Cualquier otra opción se puede pasar como un tercer parámetro opcional.fuente
Tu comentario sobre la pregunta:
Entonces, ¿por qué no hacer esto? (Nota: este es un Javascript bastante crudo. Normalmente usaría un
default
hash y lo actualizaría con las opciones pasadas usando Object.extend o JQuery.extend o similar ...)Entonces, ahora que ahora es mucho más obvio qué es opcional y qué no, todos estos son usos válidos de la función:
fuente
Puede que llegue un poco tarde a la fiesta con esta respuesta, pero estaba buscando las opiniones de otros desarrolladores sobre este mismo tema y encontré este hilo.
Estoy muy en desacuerdo con la mayoría de los que respondieron, y estoy del lado del enfoque de 'argumentos múltiples'. Mi argumento principal es que desalienta otros antipatrones como "mutar y devolver el objeto param" o "pasar el mismo objeto param a otras funciones". He trabajado en bases de código que han abusado ampliamente de este antipatrón, y la depuración de código que lo hace rápidamente se vuelve imposible. Creo que esta es una regla práctica muy específica de Javascript, ya que Javascript no está fuertemente tipado y permite tales objetos estructurados arbitrariamente.
Mi opinión personal es que los desarrolladores deben ser explícitos al llamar a funciones, evitar transmitir datos redundantes y evitar modificar por referencia. No es que estos patrones impidan escribir código conciso y correcto. Siento que hace que sea mucho más fácil para su proyecto caer en malas prácticas de desarrollo.
Considere el siguiente código terrible:
No solo requiere este tipo de documentación más explícita para especificar la intención, sino que también deja espacio para errores vagos. ¿Qué pasa si un desarrollador modifica
param1
enbar()
? ¿Cuánto tiempo crees que tomaría mirar a través de una base de código de tamaño suficiente para atrapar esto? Es cierto que este ejemplo es un poco falso porque asume que los desarrolladores ya han cometido varios antipatrones en este momento. Pero muestra cómo pasar objetos que contienen parámetros permite un mayor margen de error y ambigüedad, lo que requiere un mayor grado de conciencia y observancia de la corrección constante.¡Solo mis dos centavos sobre el tema!
fuente
Depende.
Según mi observación sobre el diseño de esas bibliotecas populares, estos son los escenarios en los que deberíamos usar el objeto de opción:
Y escenarios para usar la lista de parámetros:
fuente
El objeto es más preferible, porque si pasa un objeto es fácil ampliar el número de propiedades en esos objetos y no tiene que estar atento al orden en que se han pasado sus argumentos.
fuente
Para una función que generalmente usa algunos argumentos predefinidos, será mejor que use el objeto de opción. El ejemplo opuesto será algo así como una función que obtiene un número infinito de argumentos como: setCSS ({height: 100}, {width: 200}, {background: "# 000"}).
fuente
Me gustaría ver grandes proyectos de JavaScript.
Cosas como google map verá con frecuencia que los objetos instanciados requieren un objeto pero las funciones requieren parámetros. Creo que esto tiene que ver con los argumentos de OPTION.
Si necesita argumentos predeterminados o argumentos opcionales, un objeto probablemente sería mejor porque es más flexible. Pero si no lo hace, los argumentos funcionales normales son más explícitos.
Javascript también tiene un
arguments
objeto. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/argumentsfuente