Alcance de Javascript: incluso sin pasar o hacer global

Estoy trabajando en una secuencia de commands para un set de funciones que operan desde una sola llamada y toman una gran cantidad de parameters para devolver un valor. La function principal requiere el uso de otras 11 funciones que deben funcionar con los mismos parameters. Lo tengo estructurado algo así:

function mainfunction(param1, param2, ..., param16) { //do a bunch of stuff with the parameters return output; } function secondaryfunction1() { //gets called by mainfunction //does a bunch of stuff with the parameters from mainfunction } 

¿Hay algo que pueda hacer para que los parameters pasen a la function principal disponible para todas las funciones secundarias sin pasarlas o convertirlas en variables globales? Si no, está bien, los pasaré como parameters. Tengo curiosidad sobre si puedo hacerlo de manera más elegante o no.

Puede colocar la definición de secondaryfunction1 dentro de mainfunction :

 function mainfunction(param1, param2, ..., param16){ function secondaryfunction1() { // use param1, param2, ..., param16 } secondaryfunction1(); } 

Actualizar:

Como señaló @dystroy, esto es viable si no necesitas llamar a secondaryfunction1 en otro lugar. De dónde vendría la list de parameters en este caso, no sé.

Puede usar arguments para pasar a secondaryFunction1 todos los arguments de mainfunction . Pero eso sería una tontería.

Lo que probablemente debería hacer, y lo que generalmente se hace, es incorporar todos los parameters en un object de "opciones":

 function mainfunction(options){ secondaryfunction1(options); } function secondaryfunction1(options) { // use options.param1, etc. } // let's call it mainfunction({param1: 0, param2: "yes?"}); 

Esto lleva a otras ventajas, como

  • nombrando los parameters que pasa, no es bueno que el mantenimiento tenga que contar los parameters para saber cuál cambiar. Ninguna biblioteca en su sano juicio le permitiría pasar 16 parameters como arguments directos sin nombre a una function
  • permitiéndole pasar solo los parameters necesarios (los otros son pnetworkingeterminados)

La respuesta de @Igor (o alguna variación) es el path a seguir. Sin embargo, si tiene que usar las funciones en otro lugar (como señaló @dystroy), existe otra posibilidad. Combina tus parameters en un object y pasa ese object a las funciones secundarias.

 function combineEm() { // Get all parameters into an array. var args = [].slice.call(arguments, 0), output = {}, i; // Now put them in an object for (i = 0; i < args.length; i++) { output["param" + i] = args[i]; } return output; } 

Desde su function principal, puede hacer:

 function mainfunction(param1, param2, ..., param16) { var params = combineEm(param1, param2, ..., param16); var output = secondaryfunction(params); // etc. return output; } 

Editar: Solo quería aclarar que todas las sugerencias propuestas hasta ahora funcionan. Ellos solo tienen sus propios intercambios / beneficios.

Intenté simplemente sugerir algunos cambios a otras respuestas, pero finalmente sentí que necesitaba simplemente publicar mi solución para esto.

 var externalFn = function(options) { var str = options.str || 'hello world'; alert(str); }; var main = function(options) { var privateMethod = function() { var str = options.str || "foobar"; alert("str: " + str); }; // Bind a private version of an external function var privateMethodFromExternal = externalFn.bind(this, options); privateMethod(); privateMethodFromExternal(); }; main({ str: "abc123"}); // alerts 'str: abc123' // alerts 'abc123' main({}); // alerts 'str: foobar' // alerts 'hello world' 
  • Parece que el punto principal de la pregunta es que las funciones utilizadas por la 'function principal' no deberían tener que seguir teniendo las opciones / context pasados ​​a ellas.
  • Este ejemplo muestra cómo puedes usar privateMethods dentro de la function
  • También muestra cómo puede tomar funciones externas (que presumiblemente usa fuera de main ) y enlazar una versión de método privado de ellas para usarlas en main .
  • Prefiero usar algún tipo de object de "opciones", pero ese aspecto no es tan importante para la cuestión del scope que el OP realmente estaba preguntando. También podría usar parameters 'regulares'.

Este ejemplo se puede encontrar en el codepen .

Aquí hay una solución increíblemente traviesa, si le interesa ese tipo de cosas.

 var f1 = function() { var a = 1; var _f2 = f2.toString().replace(/^function[^{}]+{/, ''); _f2 = _f2.substr(0, _f2.length - 2); eval(_f2); } var f2 = function(a) { var a = a || 0; console.log(a); } f2(); // logs 0 f1(); // logs 1 

Ejecuta los contenidos de alguna function externa por completo en el scope actual.

Sin embargo , este tipo de engaño es casi definitivamente un indicador de que su proyecto está mal organizado. Llamar a funciones externas normalmente no debería ser más difícil que pasar un object, como sugiere la respuesta de la distroy , definir la function en el ámbito, como sugiere la respuesta de Igor , o asociar alguna function externa a this y escribir sus funciones principalmente en contra de las properties de this . Al igual que:

 var FunLib = { a : 0, do : function() { console.log(this.a); } } var Class = function() { this.a = 1; this.do = FunLib.do; this.somethingThatDependsOnDo = function() { this.a++; this.do(); } } var o = new Class(); FunLib.do() // 0 o.do() // 1 o.somethingThatDependsOnDo(); // 2 o.do() // 2 now 

De manera similar, y posiblemente mejor, se resolvió con una jerarquía de classs.

 function BasicShoe { this.steps_taken = 0; this.max_steps = 100000; this.doStep = function() { this.steps_taken++; if (this.steps_taken > this.max_steps) { throw new Exception("Broken Shoe!"); } } } function Boot { this.max_steps = 150000; this.kick_step_equivalent = 10; this.doKick = function() { for (var i = 0; i < this.kick_step_equivalent; i++) { this.doStep(); } } } Boot.prototype = new BasicShoe(); function SteelTippedBoot { this.max_steps = 175000; this.kick_step_equivalent = 0; } SteelTippedBoot.prototype = new Boot();