变量可在关闭时使用,我怎样才能解决这个问题?

我在 twitter 上使用 Typehead。我遇到了来自 Intellij 的警告。这导致每个链接的“ window.location.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

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))};
41145 次浏览

您需要在这里嵌套两个函数,创建一个新的闭包来捕获变量的值(而不是变量本身) 在关闭被创造的那一刻。您可以使用立即调用的外部函数的参数来实现这一点。替换这个短语:

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-< strong > 耶! 绑定 FTW!

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

我强烈推荐 Javascript 花园-它向我展示了这一点和更多的 Javascript 怪癖(并让我更喜欢 JS)。

另外,如果你的大脑没有融化,那天你就没有足够的 Javascript。

在第六章中,我们有了新的机会。

语句声明一个块范围局部变量,可以选择将其初始化为一个值。 Https://developer.mozilla.org/en-us/docs/web/javascript/reference/statements/let

因为 JavaScript 的唯一作用域是 功能作用域,所以您可以简单地将闭包移动到所在作用域之外的外部函数。

为了澄清@BogdanRuzhitskiy 的回答(因为我不知道如何在注释中添加代码) ,使用 let 的想法是在 for 块中创建一个局部变量:

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

除了 IE11之外,几乎所有的现代浏览器都可以使用这个功能。