w3schools utiliza tipos terminar para las instrucciones inmutabilidad funciones funcion anidadas algunas javascript closures mutable

tipos - para terminar las instrucciones en javascript se utiliza



La variable mutable es accesible desde el cierre. ¿Cómo puedo arreglar esto? (4)

Como el único alcance que JavaScript tiene es el alcance de la función , puede simplemente mover el cierre a una función externa, fuera del alcance en el que se encuentre.

Estoy usando Typeahead por twitter. Me encuentro con esta advertencia de Intellij. Esto está causando que "window.location.href" para cada enlace sea el último elemento en mi lista de elementos.

¿Cómo puedo arreglar mi código?

A continuación está mi código:

AutoSuggest.prototype.config = function () { var me = this; var comp, options; var gotoUrl = "/{0}/{1}"; var imgurl = ''<img src="/icon/{0}.gif"/>''; var target; for (var i = 0; i < me.targets.length; i++) { target = me.targets[i]; if ($("#" + target.inputId).length != 0) { options = { source: function (query, process) { // where to get the data process(me.results); }, // set max results to display items: 10, matcher: function (item) { // how to make sure the result select is correct/matching // we check the query against the ticker then the company name comp = me.map[item]; var symbol = comp.s.toLowerCase(); return (this.query.trim().toLowerCase() == symbol.substring(0, 1) || comp.c.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1); }, highlighter: function (item) { // how to show the data comp = me.map[item]; if (typeof comp === ''undefined'') { return "<span>No Match Found.</span>"; } if (comp.t == 0) { imgurl = comp.v; } else if (comp.t == -1) { imgurl = me.format(imgurl, "empty"); } else { imgurl = me.format(imgurl, comp.t); } return "/n<span id=''compVenue''>" + imgurl + "</span>" + "/n<span id=''compSymbol''><b>" + comp.s + "</b></span>" + "/n<span id=''compName''>" + comp.c + "</span>"; }, sorter: function (items) { // sort our results if (items.length == 0) { items.push(Object()); } return items; }, // the problem starts here when i start using target inside the functions updater: function (item) { // what to do when item is selected comp = me.map[item]; if (typeof comp === ''undefined'') { return this.query; } window.location.href = me.format(gotoUrl, comp.s, target.destination); return item; } }; $("#" + target.inputId).typeahead(options); // lastly, set up the functions for the buttons $("#" + target.buttonId).click(function () { window.location.href = me.format(gotoUrl, $("#" + target.inputId).val(), target.destination); }); } } };

Con la ayuda de @ cdhowie, más código: actualizaré el actualizador y también el href para el clic ()

updater: (function (inner_target) { // what to do when item is selected return function (item) { comp = me.map[item]; if (typeof comp === ''undefined'') { return this.query; } window.location.href = me.format(gotoUrl, comp.s, inner_target.destination); return item; }}(target))};



Me gustó el párrafo Closures Inside Loops de Javascript Garden

Explica tres formas de hacerlo.

La forma incorrecta de usar un cierre dentro de un bucle

for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000); }

Solución 1 con contenedor anónimo

for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { console.log(e); }, 1000); })(i); }

Solución 2 : devolver una función desde un cierre

for(var i = 0; i < 10; i++) { setTimeout((function(e) { return function() { console.log(e); } })(i), 1000) }

Solución 3 , mi favorita, donde creo que finalmente entendí bind - yaay! obligar FTW!

for(var i = 0; i < 10; i++) { setTimeout(console.log.bind(console, i), 1000); }

Recomiendo Javascript garden , me mostró esto y muchos más caprichos Javascript (y me hizo JS aún más).

ps si tu cerebro no se derritió no has tenido suficiente Javascript ese día.


Necesita anidar dos funciones aquí, creando un nuevo cierre que capture el valor de la variable (en lugar de la variable misma) en el momento en que se crea el cierre . Puede hacer esto usando argumentos para una función externa invocada inmediatamente. Reemplaza esta expresión:

function (item) { // what to do when item is selected comp = me.map[item]; if (typeof comp === ''undefined'') { return this.query; } window.location.href = me.format(gotoUrl, comp.s, target.destination); return item; }

Con este:

(function (inner_target) { return function (item) { // what to do when item is selected comp = me.map[item]; if (typeof comp === ''undefined'') { return this.query; } window.location.href = me.format(gotoUrl, comp.s, inner_target.destination); return item; } }(target))

Tenga en cuenta que pasamos el target a la función externa, que se convierte en el argumento inner_target , capturando efectivamente el valor del target en el momento en que se llama a la función externa. La función externa devuelve una función interna, que utiliza inner_target lugar de target , y inner_target no cambiará.

(Tenga en cuenta que puede cambiar el nombre de inner_target al target y estará bien, se usará el target más cercano, que sería el parámetro de la función. Sin embargo, tener dos variables con el mismo nombre en un alcance tan estrecho podría ser muy confuso y así Los he nombrado de manera diferente en mi ejemplo para que pueda ver lo que está sucediendo).