Изменяемая переменная доступна из закрытия. Как я могу это исправить?



Я использую Typeahead от twitter. Я сталкиваюсь с этим предупреждением от Intellij. Это вызывает окно".местоположение.href " для каждой ссылки, чтобы быть последним пунктом в моем списке элементов.



Как я могу исправить мой код?



Ниже приведен мой код:



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


С помощью @cdhowie, еще немного кода:
я буду обновлять программу обновления, а также href для click ()



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

4 ответов:

вам нужно вложить две функции здесь, создавая новое закрытие, которое захватывает значение переменной (вместо самой переменной) на данный момент закрытие создано. Это можно сделать с помощью аргументов для немедленно вызываемой внешней функции. Замените это выражение:

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

С этого:

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

обратите внимание, что мы передаем target во внешнюю функцию, которая становится аргументом inner_target, эффективно захватывая значение target в данный момент вызывается внешняя функция. Внешняя функция возвращает внутреннюю функцию, которая использует inner_target вместо target и inner_target не изменится.

(обратите внимание, что вы можете переименовать inner_target до target и вы будете в порядке -- ближайший target будет использоваться, который будет параметром функции. Однако наличие двух переменных с одинаковым именем в такой узкой области может быть очень запутанным, и поэтому я назвал их по-разному в своем примере, чтобы вы могли увидеть, что происходит.)

мне понравился пункт Закрытие Внутри Петли С Javascript Garden

Это объясняет три способа сделать это.

неправильный способ использования замыкания внутри петли

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

Решение 1 С анонимной обертке

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

решение 2 - возврат функции из закрытия

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

решение 3 мой любимый, где я думаю, что я наконец понял bind -ура-а-а! привязать США.

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

рекомендую Javascript garden - он показал мне это и многие другие причуды Javascript (и сделал меня похожим на JS еще больше).

p. s.Если ваш мозг не расплавился вы не имели достаточно Javascript в тот день.

в ecmascript 6 у нас есть новые возможности.

The пусть оператор объявляет локальную переменную области блока, необязательно инициализируя ее значением. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

поскольку единственная область, которую имеет JavaScript, - это функции область, вы можете просто переместить закрытие во внешнюю функцию, вне области, в которой вы находитесь.

Comments

    Ничего не найдено.