Изменяемая переменная доступна из закрытия. Как я могу это исправить?
Я использую 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))};
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