javascript - para - La variable mutable es accesible desde el cierre. ¿Cómo puedo arreglar esto?



funciones de javascript en html (3)

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))};

https://ffff65535.com


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.



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).





mutable