3

「FROM」フィールドから「TO」フィールドに値をコピーしようとしています。私の最初の試みはこれでした:

function updateToField(toField,fromField)
{
    toField.value = fromField.value}
}

function verifyFromToFields()
{
var inputs = getElementsByTagName("input");
for (var j = 0; j < inputs.length; j++)
{
    if (inputs[j].name.indexOf('FROM') != -1 && if (inputs[j+1].name.indexOf('TO') != -1)
        {
            var fromField = inputs[j];
            var toField   = inputs[j+1];
            fromField.onchange = function(){updateToField(toField,fromField)};
        }
}

ウェブサイトにはいくつかの FROM-TO ペアがあり、これは「入力」配列の最後のペアでのみ機能するようです。

それから私はこれを試しました:

function updateToField(toField,fromField)
{
    toField.value = fromField.value}
}

function verifyFromToFields()
{
var inputs = getElementsByTagName("input");
for (var j = 0; j < inputs.length; j++)
{
    if (inputs[j].name.indexOf('FROM') != -1 && if (inputs[j+1].name.indexOf('TO') != -1)
        {
            var fromField = inputs[j];
            var toField   = inputs[j+1];
            fromField.onchange = function(){updateToField(toField,this)};
        }
 }

これにより、ページの FROM フィールドが変更されると、ページの最後の TO フィールドにコピーされます。これは、値または参照としてのパラメーターについて読んだ問題の1つであると思いますが、理解できません。また、これはコードの非常に単純化されたバージョンです。実際には、入力リストに getElementsByClass 関数を入力し、子ノードを検索する必要があります。誰が何が起こっているのか手がかりを持っていますか?

4

3 に答える 3

1

その閉鎖、私はそれがあなたがそれが意味すると思うことを意味するとは思わない.

この行は次のとおりです。

     fromField.onchange = function(){updateToField(toField,this)};

は、「onchangeそのフィールドの内容を変更時のtoFieldものに割り当てる関数に割り当てることを意味します!

変数は 1 つしかないためtoField、すべての変更可能なフィールドがそれに割り当てられます。

これはうまくいきます:

var setOnChange = function(fromField, toField) {    
   fromField.onchange = function(){updateToField(toField,this)};
};

for (var j = 0; j < inputs.length; j++)
{
    if (inputs[j].name.indexOf('FROM') != -1 && if (inputs[j+1].name.indexOf('TO') != -1)
        {
            setOnChange(inputs[j], inputs[j+1]);
        }
 }

編集: Isaac は問題のより良い説明を持っているかもしれません (私は彼の解決策があまり好きではありませんが)。

于 2013-01-23T13:11:30.133 に答える
1

これは、クロージャの仕組みによるものです。onchange(ループごとに) を作成する関数を割り当てると、 を呼び出す新しい無名関数が呼び出されupdateToFieldますが、toFieldおよびthisパラメータ (または渡されているその他の値) の値は「現在の」ループにバインドされず、代わりにパラメータがバインドされますループの最後の値(これが、最後の「TO」でのみ機能する理由です)。

onchangeプロパティに新しい関数を割り当てる代わりに、Function.bindそれがある環境で実行している場合は を呼び出してみてください。ない場合はそれを書いてください。

ここにドキュメントがありますbind

したがって、次のように移動できます。

fromField.onchange = updateToField.bind(this, fromField, toField);

または、マルヴォリオが書いた別のアプローチを使用することもできます。

于 2013-01-23T13:16:05.117 に答える
1

問題は実際にはスコープに関係しています。何が起こっているかというと、関数 (に割り当てた関数onchange) が変数をキャプチャしてtoFieldおりfromField、その値が変化し続けています。ループのたびにそれらを新たに宣言しているように見えますが、それは JS の仕組みではありません。ループを通る連続したトリップはスコープを共有するため、fromField毎回同じ変数であり、反復ごとに新しい値を割り当てるだけです。したがって、最後に、すべての関数が同じfromField変数を参照します。そして、そのfromField変数には、当然、最後に割り当てた値が含まれます。

したがって、最終的にこれらすべての関数を呼び出すと、すべて同じことを行います。これは、すべてのfromFields (および、同じロジックによってtoFields) が同じ変数であるためです。これで、最後の入力のみが機能した理由が説明されました。それらは、関数を実行したときに含まれるfromFieldものです。toField

関数は新しいスコープを作成するため、中間関数を導入することでこれを修正できます。そうすれば、ループのたびに新しい変数を取得できます。

function updateToField(toField,fromField)
{
   toField.value = fromField.value;
}

function verifyFromToFields()
{
  var inputs = getElementsByTagName("input");
  for (var j = 0; j < inputs.length; j++)
  {
    function(){
      if (inputs[j].name.indexOf('FROM') != -1 && if (inputs[j+1].name.indexOf('TO') != -1)
      {
          var fromField = inputs[j];
          var toField   = inputs[j+1];
          fromField.onchange = function(){updateToField(toField,fromField)};
      }
   }();
}
于 2013-01-23T13:10:59.887 に答える