w3schools tag tab online change javascript out-parameters

tag - ¿Cuál es la mejor manera de implementar params en JavaScript?



title html w3schools (9)

Creo que esta es prácticamente la única forma (pero no soy un programador de JavaScript de hardcore).

Lo que también podría considerar es utilizar una función de devolución de llamada:

function onError(data) { // do stuff } function isLegal(odp, cb) { //... if(error) cb(error); return false; } isLegal(value, onError);

Estoy usando Javascript con jQuery. Me gustaría implementar params. En C #, se vería algo como esto:

/* * odp the object to test * error a string that will be filled with the error message if odp is illegal. Undefined otherwise. * * Returns true if odp is legal. */ bool isLegal(odp, out error);

¿Cuál es la mejor manera de hacer algo como esto en JS? ¿Objetos?

function isLegal(odp, errorObj) { // ... errorObj.val = "ODP failed test foo"; return false; }

Firebug me dice que el enfoque anterior funcionaría, pero ¿hay alguna manera mejor?


El enfoque de devolución de llamada mencionado por @Felix Kling es probablemente la mejor idea, pero también descubrí que a veces es fácil aprovechar la sintaxis literal del objeto Javascript y que su función devuelva un objeto en caso de error:

function mightFail(param) { // ... return didThisFail ? { error: true, msg: "Did not work" } : realResult; }

entonces cuando llamas a la función:

var result = mightFail("something"); if (result.error) alert("It failed: " + result.msg);

No es lujoso y difícilmente a prueba de balas, pero ciertamente está bien para algunas situaciones simples.


El enfoque habitual del caso de uso específico que describió en Javascript, y de hecho en la mayoría de los idiomas de alto nivel, es confiar en Errores (también conocidos como excepciones) para informarle cuándo ha ocurrido algo fuera de lo común. No hay forma de pasar un tipo de valor (cadenas, números, etc.) por referencia en Javascript.

Yo sólo haría eso. Si realmente necesita enviar datos personalizados a la función de llamada, puede hacer una subclase de Error.

var MyError = function (message, some_other_param) { this.message = message; this.some_other_param = some_other_param; } //I don''t think you even need to do this, but it makes it nice and official MyError.prototype = Error; ... if (something_is_wrong) throw new MyError(''It failed'', /* here''s a number I made up */ 150);

Captar excepciones es un dolor, lo sé, pero también lo es hacer un seguimiento de las referencias.

Si realmente necesita algo que se aproxime al comportamiento de las variables externas, los objetos se pasan por referencia de forma predeterminada y pueden capturar fácilmente datos de otros ámbitos:

function use_out (outvar) { outvar.message = ''This is my failure''; return false; } var container = { message : '''' }; var result = use_out(container ); console.log(container.message); ///gives the string above console.log(result); //false

Creo que esto va de alguna manera para responder a su pregunta, pero creo que todo su enfoque está roto desde el principio. Javascript admite muchas formas mucho más elegantes y potentes de obtener múltiples valores de una función. Lea un poco acerca de los generadores, los cierres, el infierno, incluso las devoluciones de llamada pueden ser agradables en ciertas situaciones.

Lo que quiero decir con todo esto es animar a cualquiera que lea esto a adaptar su estilo de programación a las limitaciones y capacidades del lenguaje que está usando, en lugar de intentar forzar lo que aprendieron de otros idiomas.

(Por cierto, algunas personas recomiendan encarecidamente los cierres porque causan efectos secundarios perversos, pero yo no los escucharía. Son puristas. Los efectos secundarios son casi inevitables en muchas aplicaciones sin un gran retroceso tedioso y evitándolos. -Obtener-desde-aquí obstáculos. Si los necesita, mantenerlos todos juntos en un alcance léxico limpio en lugar de dispersos en un infierno de oscuros punteros y referencias suena mucho mejor para mí


El siguiente es el enfoque que estoy usando. Y esta es la respuesta a esta pregunta. Sin embargo, el código no ha sido probado.

function mineCoords( an_x1, an_y1 ) { this.x1 = an_x1; this.y1 = an_y1; } function mineTest( an_in_param1, an_in_param2 ) { // local variables var lo1 = an_in_param1; var lo2 = an_in_param2; // process here lo1 and lo2 and // store result in lo1, lo2 // set result object var lo_result = new mineCoords( lo1, lo2 ); return lo_result; } var lo_test = mineTest( 16.7, 22.4 ); alert( ''x1 = '' + lo_test.x1.toString() + '', y1 = '' + lo_test.y1.toString() );


Estoy usando un método de devolución de llamada (similar al enfoque de Felix Kling ) para simular el comportamiento de los parámetros de salida. Mi respuesta difiere de la de Kling en que la función de devolución de llamada actúa como un cierre de captura de referencia en lugar de un controlador.

Este enfoque adolece de la sintaxis de la función anónima y detallada de JavaScript, pero reproduce de forma cercana la semántica de parámetros de otros idiomas.

function isLegal(odp, out_error) { //... out_error("ODP failed test foo"); // Assign to out parameter. return false; } var error; var success = isLegal(null, function (e) { error = e; }); // Invariant: error === "ODP failed test foo".


Hay otra forma en que JS puede pasar los parámetros ''out''. Pero creo que los mejores para tu situación ya fueron mencionados.

Las matrices también se pasan por referencia, no por valor. por lo tanto, al igual que puede pasar un objeto a una función, y luego establecer una propiedad del objeto en la función, y luego regresar, y acceder a la propiedad de ese objeto, también puede pasar una matriz a una función, establecer algunos valores de la matriz Dentro de la función, y retorna y accede a esos valores fuera de la matriz.

así que en cada situación puedes preguntarte: "¿es mejor una matriz o un objeto?"


Las respuestas que he visto hasta ahora no están implementando los parámetros en JavaScript, ya que se usan en C # (la palabra clave out ). Son simplemente una solución que devuelve un objeto en caso de error.

Pero, ¿qué haces si realmente necesitas parámetros?

Debido a que Javascript no lo admite directamente, necesita crear algo que esté cerca de los parámetros de salida de C #. Eche un vistazo a este enfoque, estoy emulando la función DateTime.TryParse de C # s en JavaScript. El parámetro out es el resultado, y debido a que JavaScript no proporciona una palabra clave out, estoy usando .value dentro de la función para pasar el valor fuera de la función (inspirado en la sugerencia de MDN ):

// create a function similar to C#''s DateTime.TryParse var DateTime = []; DateTime.TryParse = function(str, result) { result.value = new Date(str); // out value return (result.value != "Invalid Date"); }; // now invoke it var result = []; if (DateTime.TryParse("05.01.2018", result)) { alert(result.value); } else { alert("no date"); };

Ejecuta el fragmento y verás que funciona. Tenga en cuenta que el result debe inicializarse como una matriz vacía [] , antes de llamar a la función. Esto es necesario porque dentro de la función se "inyecta" la propiedad .value .

Ahora puede usar el patrón anterior para escribir una función como la que está en su pregunta (esto también le muestra cómo emular el nuevo parámetro de descarte conocido como out _ en C #: en JavaScript pasamos [] como se muestra a continuación):

// create a function similar to C#''s DateTime.TryParse var DateTime = []; DateTime.TryParse = function(str, result) { result.value = new Date(str); // out value return (result.value != "Invalid Date"); }; // returns false, if odb is no date, otherwise true function isLegal(odp, errorObj) { if (DateTime.TryParse(odp, [])) { // discard result here by passing [] // all OK: leave errorObj.value undefined and return true return true; } else { errorObj.value = "ODP failed test foo"; // return error return false; } } // now test the function var odp = "xxx01.12.2018xx"; // invalid date var errorObj = []; if (!isLegal(odp, errorObj)) alert(errorObj.value); else alert("OK!");

Nota: en lugar de usar un parámetro de descarte como se muestra arriba, en JavaScript también se puede usar un chequeo para undefined , es decir, dentro del control de funciones para

if (result === undefined) { // do the check without passing back a value, i.e. just return true or false };

Entonces es posible omitir el result como un parámetro completamente si no es necesario, por lo que podría invocarlo como

if (DateTime.TryParse(odp)) { // ... same code as in the snippet above ... };


No voy a publicar ningún code pero lo que no se puede hacer aquí en estas respuestas es poner la rima a la razón . Estoy trabajando en la arena JS nativa y surgió el problema de que algunas native API calls deben transformarse porque no podemos escribir en los parámetros sin feos trucos vergonzosos.

Esta es mi solución:

// Functions that return parameter data should be modified to return // an array whose zeroeth member is the return value, all other values // are their respective 1-based parameter index.

Eso no significa definir y devolver cada parámetro. Sólo los parámetros que reciben la salida.

El motivo de este enfoque es, por lo tanto: es posible que se necesiten Multiple return values para cualquier número de procedimientos. Esto crea una situación en la que los objetos con valores con nombre (que en última instancia no estarán sincronizados con el contexto léxico de todas las operaciones), deben memorizarse constantemente para que funcionen adecuadamente con los procedimientos.

Usando el método prescrito, solo tiene que saber what you called y where you should be looking lugar de tener que saber qué es lo que está buscando .

También existe la ventaja de que se pueden escribir algoritmos " robustos y estúpidos " para envolver las llamadas de procedimiento deseadas para que esta operación sea "más transparente".

Sería prudente utilizar un object , una function o una array (todos los cuales son objetos) como un parámetro de "escritura de devolución de salida", pero creo que si se debe realizar cualquier trabajo extraño, debe hacerlo el uno escribiendo el kit de herramientas para facilitar las cosas, o ampliar la funcionalidad.

Esta es una respuesta única para cada ocasión, que mantiene a las APIs con el aspecto que debería tener a primera vista, en lugar de parecerlo y tener todas las similitudes con un tejido de encajes de adoquines de código de espagueti que no puede descubrir si es una definición o datos

Felicitaciones y buena suerte.

Estoy usando el webkitgtk3 y conectando algunos procedimientos nativos de C Library. por lo que este ejemplo de código comprobado podría servir al menos como ilustración.

// ssize_t read(int filedes, void *buf, size_t nbyte) SeedValue libc_native_io_read (SeedContext ctx, SeedObject function, SeedObject this_object, gsize argument_count, const SeedValue arguments[], SeedException *exception) { // NOTE: caller is completely responsible for buffering! /* C CODING LOOK AND FEEL */ if (argument_count != 3) { seed_make_exception (ctx, exception, xXx_native_params_invalid, "read expects 3 arguments: filedes, buffer, nbyte: see `man 3 read'' for details", argument_count ); return seed_make_undefined (ctx); } gint filedes = seed_value_to_int(ctx, arguments[0], exception); void *buf = seed_value_to_string(ctx, arguments[1], exception); size_t nbyte = seed_value_to_ulong(ctx, arguments[2], exception); SeedValue result[3]; result[0] = seed_value_from_long(ctx, read(filedes, buf, nbyte), exception); result[2] = seed_value_from_binary_string(ctx, buf, nbyte, exception); g_free(buf); return seed_make_array(ctx, result, 3, exception); }


Sí, como usted mismo mencionó, los objetos son la mejor y la única forma de pasar datos por referencia en JavaScript. Mantendría su función isLegal como tal y simplemente la llamaría así:

var error = {}; isLegal("something", error); alert(error.val);