Pasar argumentos a otra función de JavaScript

386

He intentado lo siguiente sin éxito:

function a(args){
    b(arguments);
}

function b(args){
    // arguments are lost?
}

a(1,2,3);

En la función a, puedo usar la palabra clave argumentos para acceder a una matriz de argumentos, en la función b se pierden. ¿Hay alguna forma de pasar argumentos a otra función de JavaScript como intento hacer?

Anders Nygaard
fuente
3
@ BobStein-VisiBone estuvo de acuerdo. Además, tenga en cuenta que en realidadarguments no es una matriz (sino más bien un objeto que implementa una semántica similar a una matriz ) y, por lo tanto, a primera vista no está del todo claro si se puede usar de la misma manera que una matriz real.
Julio
@Jules todavía vota para reabrir después de todos estos años. ¿Cuál es la insignia para quemar el valioso trabajo de otras personas? Muchos de esos para todos.
Bob Stein

Respuestas:

542

Use .apply()para tener el mismo acceso a la argumentsfunción in b, así:

function a(){
    b.apply(null, arguments);
}
function b(){
   alert(arguments); //arguments[0] = 1, etc
}
a(1,2,3);​

Puedes probarlo aquí .

Nick Craver
fuente
21
@Brett: puede copiarlo en una matriz y luego manipularlo antes de pasarlo, por ejemplo:var copy = [].slice.call(arguments); <remove what you want> myFunc.apply(this, copy);
Nick Craver
18
pero usarlo de applyesta manera podría arruinar el alcance de b(si es alguna función interna de un objeto, por ejemplo)
vsync
3
@vsync buen punto, pero el problema es fácil de resolver: pase el objeto como primer argumento para aplicar.
Tad Lispy
11
no tiene sentido utilizar "argumentos" y "argumentos" juntos ...
tio
3
Pero entonces el "esto" podría cambiarse a algo diferente al original de b esto.
trusktr 01 de
223

Operador extendido

El operador de propagación permite que una expresión se expanda en lugares donde se esperan múltiples argumentos (para llamadas a funciones) o múltiples elementos (para literales de matriz).

ECMAScript ES6 agregó un nuevo operador que le permite hacer esto de una manera más práctica: ... Operador extendido .

Ejemplo sin usar el applymétodo:

function a(...args){
  b(...args);
  b(6, ...args, 8) // You can even add more elements
}
function b(){
  console.log(arguments)
}

a(1, 2, 3)

Note Este fragmento devuelve un error de sintaxis si su navegador todavía usa ES5.

Nota del editor: Desde los usos de fragmento console.log(), debe abrir la consola JS de su navegador para ver el resultado - no habrá ninguna consecuencia en la página.

Mostrará este resultado:

Imagen de ejemplo de argumentos de operador Spread

En resumen, el operador de propagación se puede usar para diferentes propósitos si está usando matrices, por lo que también se puede usar para argumentos de función, puede ver un ejemplo similar explicado en los documentos oficiales: parámetros de descanso

Walter Chapilliquen - wZVanG
fuente
66
Este es un operador muy agradable y estoy ansioso por usarlo. Sin embargo, aún no sucederá. El único navegador que ya admite el operador de propagación es FF en este momento. Consulte la tabla de compatibilidad para obtener datos completos y actualizados: kangax.github.io/compat-table/es6/#spread_%28...%29_operator
TMG
10
¿Por qué no debería ser usado? Es relativamente fácil transpilar con babel, obtienes todas las nuevas funciones y mucha más compatibilidad con navegadores antiguos.
adgelbfish
Esto es mejor que la primera solución porque funciona en función definida con el operador de flecha.
sarfata
No necesitas ...argsen la afunción. Simplemente puede hacer una función sin argumentos y pasarlos a bcon...arguments
cronoklee
1
Para cualquiera que lea esta respuesta: Contrariamente al comentario de @ cronoklee, especificar explícitamente ...argscomo aentrada puede ser importante si tiene funciones anidadas.
Arshia001
81

La explicación de que ninguna de las otras respuestas proporciona es que los argumentos originales todavía están disponibles, pero no en la posición original en el argumentsobjeto.

los arguments objeto contiene un elemento para cada parámetro real proporcionado a la función. Cuando se llama a austed suministra tres argumentos: los números 1, 2y, 3. Entonces, argumentscontiene [1, 2, 3].

function a(args){
    console.log(arguments) // [1, 2, 3]
    b(arguments);
}

Cuando llama b, sin embargo, pasa exactamente un argumento:a el argumentsobjeto de. Por lo tanto, argumentscontiene [[1, 2, 3]](es decir, un elemento, que es ael argumentsobjeto, que tiene propiedades que contienen los argumentos originales para a).

function b(args){
    // arguments are lost?
    console.log(arguments) // [[1, 2, 3]]
}

a(1,2,3);

Como demostró @Nick, puede usar applypara proporcionar un argumentsobjeto establecido en la llamada.

Lo siguiente logra el mismo resultado:

function a(args){
    b(arguments[0], arguments[1], arguments[2]); // three arguments
}

Pero apply es la solución correcta en el caso general.

Wayne
fuente
¿Deberías pasar siempre thisa apply?
Flimm
1
@ Flimm: sí, dado que los argumentos son el segundo argumento, debe haber algo para el primer argumento (puede ser nulo ).
RobG
0

prueba esto

function global_func(...args){
  for(let i of args){
    console.log(i)
  }
}


global_func('task_name', 'action', [{x: 'x'},{x: 'x'}], {x: 'x'}, ['x1','x2'], 1, null, undefined, false, true)




//task_name
//action
//(2) [{...},
//    {...}]
//    {
//        x:"x"
//    }
//(2) [
//        "x1",
//        "x2"
//    ]
//1
//null
//undefined
//false
//true
//func
Jaber Alshami
fuente