2010-06-30 13 views
47

que tienen una función de JavaScript típico con algunos parámetrosjavascript argumentos opcionales en función de

my_function = function(content, options) { action } 

si llamo a la función como tal:

my_function (options) 

el argumento "opciones" se pasa como "contenido"

¿cómo soluciono esto para poder aprobar ambos argumentos o solo uno? gracias

Respuesta

81

Usted tiene que decidir lo cual parámetro que desea tratar un solo argumento. No puede tratarlo como ambos, content y options.

veo dos posibilidades:

  1. sea cambiando el orden de los argumentos, es decir function(options, content)
  2. Compruebe si options se define:

    function(content, options) { 
        if(typeof options === "undefined") { 
         options = content; 
         content = null; 
        } 
        //action 
    } 
    

    Pero entonces usted tiene que documentar adecuadamente, qué pasa si solo pasa un argumento a la función, ya que esto no está inmediatamente claro mirando la firma.

+1

undefined es una propiedad global con un valor constante, por lo que no es necesario que la cites. En navegadores obsoletos, podría establecer accidentalmente un valor arbitrario, pero este no es el caso de los navegadores de hoy en día. – andreszs

+5

@Andrew: 'typeof' siempre devuelve una cadena. Alternativamente, 'if (opciones === undefined)' funcionaría también. Pero como dijiste, es posible anular 'undefined' en navegadores más antiguos, por lo que la práctica prevalente (creo) es no usar' indefinido' (a menos que hayas definido explícitamente alguna parte). –

+1

no compare cadenas con '===', no es necesario tener el mismo objeto si tiene el mismo contenido. – inetphantom

14

De esta manera:

my_function (null, options) // for options only 
my_function (content) // for content only 
my_function (content, options) // for both 
0

obtendrá el valor del argumento de la ONU aprobó como no definidos. Pero en su caso, debe pasar al menos valor nulo en el primer argumento.

O usted tiene que cambiar la definición del método como

my_function = function(options, content) { action } 
21
my_function = function(hash) { /* use hash.options and hash.content */ }; 

y luego llamar a:

my_function ({ options: options }); 
my_function ({ options: options, content: content }); 
+0

lo que es en realidad de hash? – BlueBird

+0

¿Por qué lo llamas "hash"? –

+0

@Muneer: es solo un ejemplo. – Sarfraz

0

llamada como ésta

my_function ("", options); 
3

O también se puede diferenciar por el tipo de contenido que tienes. Opciones solía ser un objeto el contenido se utiliza para ser una cadena, por lo que se podría decir:

if (typeof content === "object") { 
    options = content; 
    content = null; 
} 

O si usted está confundido con el cambio de nombre, puede utilizar la matriz de argumentos que puede ser más sencillo:

if (arguments.length === 1) { 
    options = arguments[0]; 
    content = null; 
} 
+1

Prefiero esta variación: 'var optional_arg = arguments.length> = 1? argumentos [0]: 'valor predeterminado'; ' –

1

Puede pasar todos sus argumentos opcionales en un objeto como primer argumento. El segundo argumento es tu devolución de llamada.Ahora se puede aceptar tantos argumentos como que quiere en su primer objeto argumento, y que sea opcional, así:

function my_func(op, cb) { 
    var options = (typeof arguments[0] !== "function")? arguments[0] : {}, 
     callback = (typeof arguments[0] !== "function")? arguments[1] : arguments[0]; 

    console.log(options); 
    console.log(callback); 
} 

Si usted lo llama sin pasar el argumento opciones, se usará por defecto un objeto vacío:

my_func(function() {}); 
=> options: {} 
=> callback: function() {} 

Si usted lo llama con el argumento de opciones de obtener todos sus parametros:

my_func({param1: 'param1', param2: 'param2'}, function() {}); 
=> options: {param1: "param1", param2: "param2"} 
=> callback: function() {} 

obviamente, esto podría ser ajustado para trabajar con más argumentos que dos, pero conseguir más de los co nfusing. Si puede usar un objeto como su primer argumento, entonces puede pasar una cantidad ilimitada de argumentos usando ese objeto. Si necesita absolutamente más argumentos opcionales (por ejemplo, my_func (arg1, arg2, arg3, ..., arg10, fn)), le sugiero que use una biblioteca como ArgueJS. No lo he usado personalmente, pero parece prometedor.

+0

muchas gracias ... Exactamente estoy buscando esto. Tengo 6 parámetros en mi función. algunos parámetros tienen valores predeterminados. Pero algunos parámetros deberían establecerse en la llamada a la función. Creo que esta respuesta será adecuada para mi caso. Gracias de nuevo ... :) –

-1

También puede poner una marca en la acción como: options = !options ? content : options que establece opciones para el primer argumento si hay segunda fue aprobada en, y luego que acaba de establecer el contenido en nulo (o lo ignoran, sin embargo usted quiere comprobar eso)

2

Hay 2 formas de hacerlo.

1)

function something(options) { 
    var timeToLive = options.timeToLive || 200; // default to 200 if not set 
    ... 
} 

2)

function something(timeToDie /*, timeToLive*/) { 
    var timeToLive = arguments[1] || 200; // default to 200 if not set 
    .. 
} 

En 1), options es un objeto de JS con lo que cada vez se requieren atributos. Esto es más fácil de mantener y extender.

En 2), la firma de la función es clara para leer y comprender que se puede proporcionar un segundo argumento. He visto este estilo usado en el código y la documentación de Mozilla.

1

He creado una biblioteca simple para manejar argumentos opcionales con funciones de JavaScript, vea https://github.com/ovatto/argShim. La biblioteca está desarrollada con Node.js en mente, pero debe ser fácilmente portada para trabajar con, p. Ej. navegadores.

Ejemplo:

var argShim = require('argShim'); 
var defaultOptions = { 
    myOption: 123 
}; 

var my_function = argShim([ 
    {optional:'String'}, 
    {optional:'Object',default:defaultOptions} 
    ], function(content, options) { 
    console.log("content:", content, "options:", options); 
    }); 

my_function(); 
my_function('str'); 
my_function({myOption:42}); 
my_function('str', {myOption:42}); 

Salida:

content: undefined options: { myOption: 123 } 
content: str options: { myOption: 123 } 
content: undefined options: { myOption: 42 } 
content: str options: { myOption: 42 } 

El objetivo principal de la biblioteca son las interfaces de módulos que usted necesita para ser capaz de manejar diferentes invocaciones de funciones del módulo exportados.

+0

Esto es muy detallado, además usa la palabra "predeterminado" que ya es una palabra clave en JS. No recomendaría –

+0

Claro que puede ser un poco detallado, pero proporciona algunas características adicionales además de la comprobación de presencia de argumento simple. Y escribir las mismas características en cada función será aún más detallado. Además, aunque a algunos no les gusta, las palabras clave reservadas se pueden usar libremente como nombres de propiedad en ES5. Sin embargo, toda la lib fue escrita muy apresuradamente para que tu (y el mío) kilometraje varíen :) – ovatto

1

Solo patear un caballo muerto hace mucho tiempo, porque tuve que implementar un argumento opcional en el medio de dos o más argumentos requeridos. Use la matriz arguments y use último como el argumento obligatorio no opcional.

my_function() { 
    var options = arguments[argument.length - 1]; 
    var content = arguments.length > 1 ? arguments[0] : null; 
} 
1

Hay una buena lectura en Parámetros por defecto en ES6 on the MDN website here.
En ES6 ahora se puede hacer lo siguiente:

secondDefaultValue = 'indirectSecondDefaultValue'; 

function MyObject(param1 = 'firstDefaultValue', param2 = secondDefaultValue){ 
    this.first = param1; 
    this.second = param2; 
} 

Se puede usar esta también de la siguiente manera:

var object = new MyObject(undefined, options); 

que establecerá el valor predeterminado para la primera 'firstDefaultValue'param1 y su options para la segunda param2.

Here a demonstration in a fiddle

0

Con ES6:

function test(a, b = 3) { 
    console.log(a, ' ', b); 
} 

test(1);  // Output: 1 3 
test(1, 2); // Output: 1 2 
Cuestiones relacionadas