3

コードを数時間デバッグしようとしましたが、何も得られませんでした。問題は、イベント リスナーでdocument.forms[0][i] (イテレータとしてi) を使用しようとするたびにエラーが報告される理由がまったく意味をなさないことですが、 「this」はコードを満たします。

//broken
var addListeners = function() {
    var i;
    var formFields = document.forms[0];
    var formSubmit = formFields["submit"];

    for (i = 0; i < formFields.length; i++) {
        if (formFields[i] != formSubmit) {
            formFields[i].onblur = (function () {
                checkNonEmpty(formFields[i]);
            });
        }
    }
};

//works
var addListeners = function() {
    var i;
    var formFields = document.forms[0];
    var formSubmit = formFields["submit"];

    for (i = 0; i < formFields.length; i++) {
        if (formFields[i] != formSubmit) {
            formFields[i].onblur = (function () {
                checkNonEmpty(this);
            });
        }
    }
};

"this"は document.forms[0][i] を参照していませんか?... formFields は document.forms[0] を参照しています。ただし、まったく同じコード(formFields[i] が "this" の場合) は問題なく動作します。

これがデモです:http://jsfiddle.net/PbHwy/

4

3 に答える 3

3

クラニオの答えにはすでに問題の根源が含まれています。これを取り除くには、formFields[i]クロージャーを使用して含めることができます

var blurCallbackGenerator = function(element){
    return function () {
        checkNonEmpty(element);
    };
};
formFields[i].onblur = blurCallbackGenerator(formFields[i]);

/* // dense version:
formFields[i].onblur = (function(element){
    return function () {
        checkNonEmpty(element);
    };
})(formFields[i]);
*/

または単にを使用しthisます。

参照:

于 2012-06-16T08:24:06.737 に答える
3

formFieldsイベントリスナーの外側の(またはより良い、異なる)スコープで定義するためです。イベントリスナーが呼び出されると、addListenersを定義する関数ではformFieldsなく「独立して」呼び出されるため、参照が失われ、その値は未定義になります (ただしthis、そのスコープに依存しないため機能します)。

于 2012-06-16T08:17:35.610 に答える
1

問題は、i(各ハンドラーで参照される) 変数が、それぞれのハンドラーでまったく同じ変数であり、ループが終了するまでに値formFields.length+1を持つため、すべてのハンドラーで間違っていることです。代わりにこれを試してください [注: 以下は、私が編集する前に非常に間違ったことを言っていました -- 私の間違いを指摘してくれた Zeta に感謝します]:

var addListeners = function() {
    var i;
    var formFields = document.forms[0];
    var formSubmit = formFields["submit"];

    for (i = 0; i < formFields.length; i++) {
        if (formFields[i] != formSubmit) {
            formFields[i].onblur = (function(j) {
                return (function () {
                    checkNonEmpty(formFields[j]);
                })(i);
            });
        }
    }
};

そして、それが機能することがわかります(私が気付いていない別のバグがない限り)。

Javascript 1.7 以降のみをサポートする余裕がある場合は、代わりに古いコードを記述して、次のようにすることができforますfor (let i=0; i<formFields.length; i++)。しかし、あなたはおそらくできません。

于 2012-06-16T08:20:14.127 に答える