63

私はすべての 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 を介してこのようなコードを微調整する方法はありますか?

4

6 に答える 6

67

Douglas Crockford は、上記を達成するための新しい慣用的な方法を持っています。彼の古い手法は、内部関数を使用して変数をバインドすることでしたが、新しい手法は関数メーカーを使用します。彼の「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);
}
于 2010-06-14T15:36:41.503 に答える
13

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

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

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

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

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

これについては、スタック オーバーフロー: JSlint エラー 'Don't make functions within a loop.'で同様の質問をしたときに、私よりも賢い他の人によって、より多くのコメント/ディスカッションが行われました 。Javascript自体についての質問につながる

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

于 2011-01-21T12:14:30.010 に答える
8

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

于 2010-06-14T13:40:54.707 に答える
5

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);
}
于 2012-02-20T00:36:32.197 に答える
3

移動するだけです:

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

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

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

次に、ループ内に次のようになります。

prototype[prop] = makeFn(...)

于 2010-06-14T15:31:19.293 に答える