TwitterでTypeaheadを使用しています。私は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の助けを借りて、いくつかのコードを追加します。アップデータを更新し、click()の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))};
ここで2つの関数をネストし、(変数自体ではなく)変数の値をキャプチャする新しいクロージャーを作成する必要がありますクロージャーが作成された瞬間。これは、すぐに呼び出される外部関数の引数を使用して実行できます。次の式を置き換えます。
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
の値を効果的にキャプチャします。外部関数は、target
の代わりにinner_target
を使用する内部関数を返します。inner_target
は変更されません。
(inner_target
の名前をtarget
に変更でき、大丈夫です。最も近いtarget
が使用されます。これは関数パラメーターになります。ただし、このような狭い範囲の同じ名前は非常に紛らわしいかもしれないので、私の例では異なる名前を付けました。
Closures Inside LoopsfromJavascript Garden
それを行う3つの方法を説明します。
ループ内でクロージャを使用する間違った方法
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)
}
Solution 3、私のお気に入りで、bind
-yaay!バインドFTW!
for(var i = 0; i < 10; i++) {
setTimeout(console.log.bind(console, i), 1000);
}
Javascript garden をお勧めします-これは私にこれともっと多くのJavascriptの癖を見せてくれました(そして私はJSをもっと好きになりました)。
p.s。脳が溶けなかったら、その日は十分なJavascriptを持っていませんでした。
Ecmascript 6には、新しい機会があります。
letステートメントは、ブロックスコープのローカル変数を宣言し、オプションでそれを値に初期化します。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
JavaScriptのスコープはfunctionスコープのみであるため、単純にクロージャーを現在のスコープ外の外部関数に移動できます。