2011-03-08 7 views
50

lectura a través this, me vino a la broca en los valores por defecto para los argumentos de la función:defecto ordenar

fill = (container, liquid = "coffee") -> 
    "Filling the #{container} with #{liquid}..." 

Eso es ordenada, pero luego intentó esto:

fill = (container="mug", liquid = "coffee") -> 
    "Filling the #{container} with #{liquid}..." 

alert fill(liquid="juice") 

y se lo inesperado alerta con "Filling the juice with coffee...". Entonces intenté esto:

fill = (container="mug", liquid = "coffee") -> 
    "Filling the #{container} with #{liquid}..." 

alert fill(null, "juice") 

y funcionó. Aunque no es lindo. ¿Hay una mejor manera, o es esta la manera idiomática de hacer esto?

+10

se ve feo o tiene un sabor divertido, difícil de llamar – Ron

Respuesta

83
fill = ({container, liquid} = {}) -> 
    container ?= "mug" 
    liquid ?= "coffee" 

    "Filling the #{container} with #{liquid}..." 

alert fill(liquid: "juice", container: "glass") 
alert fill() 
fill = (quantity="500 mL", {container, liquid} = {}) -> 
    container ?= "mug" 
    liquid ?= "coffee" 

    "Filling the #{container} with #{quantity} of #{liquid}..." 

alert fill("1L", liquid: "juice", container: "glass") 
alert fill() 
alert fill "1L" 
alert fill "1L", liquid: "water" 
+4

Esta es definitivamente la forma canónica de hacerlo. No hay forma de que CoffeeScript agregue argumentos nombrados a JavaScript directamente, pero su sintaxis de objeto de coincidencia de patrones es la mejor opción. Lamentablemente, la coincidencia de patrones no se puede combinar con los valores predeterminados en este momento, por lo que la propuesta de Jeremy es lo más breve posible. –

+0

Solo quería decir lo útil que encontré esta respuesta, gracias. +1 – iain

+18

Debería ser 'fill = ({container, liquid} = {}) -> ...' si desea poder llamar a la función sin ningún parámetro, 'fill()'. Además, puede usar los valores predeterminados normales para los parámetros posicionales: 'fill = (quantity =" 500 ml ", {container, liquid} = {}) -> ...' se puede llamar 'fill()', 'fill" 1L "' o con cualquier combinación de los parámetros nombrados, por ejemplo 'fill" 1L ", líquido:" juice "'. –

4

Actualmente, no hay forma de llamar con argumentos con nombre. Se requeriría conocer los argumentos (nombres, posiciones y/o valores por defecto) en el sitio de la llamada, lo que no siempre es factible en javascript/coffeescript.

En cambio si tiene muchos argumentos y que desea nombrarlos y tienen valores por defecto, se podría hacer algo como esto:

fill = (opts = {}) -> 
    opts.container ?= "mug" 
    opts.liquid ?= "coffee" 
    "Filling the #{opts.container} with #{opts.liquid}..." 

alert fill 
    liquid:"juice" 
    container:"cup" 

alert fill 
    liquid:"juice" 

alert fill() 
8

Amir y Jeremy ya tienen esto. Como señalan, container="mug" en la lista de argumentos de una función es realmente solo una abreviatura de container ?= "mug" en el cuerpo de la función.

Permítanme añadir que al llamar a funciones,

fill(liquid="juice") 

significa lo mismo que en JavaScript: En primer lugar, asignar el valor a la variable "juice"liquid; luego pase liquid junto al fill. CoffeeScript no hace nada especial aquí, y liquid tiene el mismo alcance en esa situación que lo haría fuera de la llamada a la función.

Por cierto, he sugerido que la sintaxis argumento por defecto debería ser más potente permitiendo que los argumentos que hay que saltar (por ejemplo (first, middle ?= null, last) -> sería asignar valores a first y last si sólo se pasan dos argumentos), y que el ?= la sintaxis debe usarse en lugar de =. Es posible que desee expresar su apoyo a esa propuesta aquí: issue 1091.

+0

Creo que los 'argumentos opcionales de función' funcionan bien en frameworks como jQuery pero disminuyen un poco la legibilidad.Si hay toneladas de funciones que usan este estilo en algún fragmento de código, podría tener que mirar cada definición de función para tener una idea de cuáles son los parámetros. Por ejemplo: 'animate 100, ->' vs 'animate {delay: 100}, ->'. Solo para que también puedas hacer 'animate ->'. – Amir

+1

Gracias, no me había dado cuenta de que era solo asignación. Demasiado Python, probablemente. – nmichaels