web-dev-qa-db-ja.com

jslintエラー「ループ内で関数を作成しないでください」を修正する方法は?

すべてのJSコードがjslintを通過するように取り組んでいます。場合によっては、後で適切に修正するために、レガシコードのパスを取得するオプションを大幅に調整することもあります。

Jslintが、回避策がないことについて不満を言うことが1つあります。これは、このような構造を使用すると、「ループ内で関数を作成しないでください」というエラーが表示されます。

for (prop in newObject) {
    // Check if we're overwriting an existing function
    if (typeof newObject[prop] === "function" && typeof _super[prop] === "function" &&
        fnTest.test(newObject[prop])) {
        prototype[prop] = (function(name, func) {
            return function() {
                var result, old_super;

                old_super = this._super;
                this._super = _super[name];
                result = func.apply(this, arguments);
                this._super = old_super;

                return result;
            };
        })(prop, newObject[prop]);
    }
}

このループは、既存のクラスを拡張するクラスが拡張クラスのメンバーを呼び出すときに拡張クラスのスーパープロパティを保持する、古典的な継承のJS実装の一部です。明確にするために、上記の実装は、John Resigによる ブログ投稿 に触発されています。

しかし、ループ内で作成された関数の他のインスタンスもあります。

これまでの唯一の回避策は、これらのJSファイルをjslintから除外することですが、継続的な統合とビルドのワークフローの一部としてコード検証と構文チェックにjslintを使用したいと思います。

このような機能を実装するより良い方法はありますか、jslintを介してこのようなコードを微調整する方法はありますか?

60
Ernelli

ダグラス・クロックフォードは、上記を達成するための新しい慣用的な方法を持っています-彼の古い技術は、変数をバインドするために内部関数を使用することでしたが、新しい技術は関数メーカーを使用します。 「Function the Ultimate」トークのスライドのスライド74 を参照してください。 [このスライドシェアはもう存在しません]

怠け者の場合、コードは次のとおりです。

function make_handler(div_id) {
    return function () {
        alert(div_id);
    };
}
for (i ...) {
    div_id = divs[i].id;
    divs[i].onclick = make_handler(div_id);
}
65
Skilldrick

(投稿されてから何ヶ月もたった今この質問に出くわしました...)

ループ内で関数を作成すると、ループの反復ごとに関数のインスタンスが作成されます。作成されている関数が実際に各反復で異なる場合を除き、ループの外側に関数ジェネレーターを配置する方法を使用します-そうすることは単なる食器ではなく、コードを読んでいる他の人にこれがあなたの意図であることを知らせます。

関数が実際に反復で異なる値に割り当てられているのと同じ関数(または反復で生成されたオブジェクト)である場合、代わりに関数を名前付き変数に割り当て、その関数の単一インスタンスを割り当て内で使用する必要がありますループ:

handler = function (div_id) {
    return function() { alert(div_id); }
}

for (i ...) {
    div_id = divs[i].id;
    divs[i].onclick = handler(div_id);
}

Stack Overflowで同様の質問をここで提起したとき、これに関するより大きなコメント/議論が私より賢い他の人によってなされました: JSlintエラー 'Do n't make functions in loop。 JavaScript自体についての質問につながります

JSLintに関して:はい、それは独断的で慣用的です。そうは言っても、通常は「正しい」です。JSLintについて否定的に発言する多くの人々が、実際にはJavascript(の微妙な部分)を理解していないことがわかります。

12
Zhami

文字通り、次のようにして問題を解決しますaround

  1. .jshintrcファイルを作成します
  2. .jshintrcファイルに次の行を追加します

    {"loopfunc" : true, // tolerate functions being defined in loops }

10
lifebalance

JSLintは単なるガイドであり、常にルールを順守する必要はありません。問題は、それが参照しているという意味で、ループ内で関数を作成していないということです。アプリケーションでクラスを作成するのは一度だけで、何度も作成することはありません。

7
Evan Trimboli

JQueryを使用している場合、ループで次のようなことをしたい場合があります。

_for (var i = 0; i < 100; i++) {
  $("#button").click(function() {
    alert(i);
  });
}
_

JSLintを満たすために、これを回避する1つの方法は(JQuery 1.4.3+で).click()に追加のハンドラデータ引数を使用することです。

_function new_function(e) {
  var data = e.data; // from handler
  alert(data); // do whatever
}

for (var i = 0; i < 100; i++) {
  $("#button").click(i, new_function);
}
_
5
jevon

次を移動するだけです:

_(function (name, func) {...})()_

次のように、ループをブロックして変数に割り当てます。

var makeFn = function(name, func){...};

次に、ループ内にあります:

prototype[prop] = makeFn(...)

3
Matt Eberts