javascript - 深い理解: ループで作成した日付配列の内容にコード構造がどのように影響するか
背景説明
ループを使って日付の配列を定義することについて質問しました。
配列は「dateinterval」という名前で宣言された変数に基づいて定義されています。私が設計したコードの方法では、別のループに関連するエラーメッセージが発生し、別のユーザーが私のために別のループを提供してくれ、それが解決しました。
二つの異なる解決策を注意深く比較した今、なぜ同じ結果が得られないのか全く理解できません。
私のコード
私はUTC形式の日付の配列を定義するために以下のコードを作成しました。しかし、結果は1970年1月1日00:00:00以来のミリ秒で表された日付の配列になります。つまり、別の言い方をすれば数字です。
for (var i=0; i < difference; i++){
dateinterval[dateinterval.length] = dateinterval[0].setDate(datointerval[0].getDate() + i);
};
適切な解決策
以下のコードは、別のユーザーから提供された正しいコードです(改めてありがとうございます!)。このコードはUTCの日付の配列を定義します。
for (var i = 0; i < difference; i++) {
var dt = new Date(dateinterval[0]);
dt.setDate(dt.getDate() + i);
dateinterval[dateinterval.length] = dt;
};
私が理解できないこと
二つの異なる解法を見比べて違いを理解しようとして、ほとんど目が見えなくなりそうで、ただただ理解できません。
素人目には、2つのコードはまったく同じ操作を行っており、違いは構造の仕方だけのように見えます。私は、setDate がミリ秒を返し、私のコードではこれらのミリ秒が配列に代入されていたと聞いています。しかし、正しい解法では、変数 DT も setDate の値が代入されており、私の理解ではこれもミリ秒であるはずです。それならなぜ次の行が:
dateinterval[dateinterval.length] = dt;
dateinterval 配列にミリ秒を割り当てませんか?
誰か、私がJavascriptをよりよく理解できるように、単に動く解決策をコピーするだけでなく説明してくれますか?
回答 #1
あなたがする時:
dateinterval[dateinterval.length] = dateinterval[0].setDate(datointerval[0].getDate() + i);
あなたは dateinterval[0].setDate(…) の戻り値を dateinterval[…] に代入しています。その戻り値は Date オブジェクトの timeclip、つまり内部時間値(1970年1月1日からのミリ秒)です。詳しくは ECMA-262 §20.3.4.20 を参照してください。
まず日付を変更する必要があります:
dateinterval[0].setDate(datointerval[0].getDate() + i);
次に、そのオブジェクトへの参照を割り当てます:
dateinterval[dateinterval.length] = dateinterval[0];
編集
簡単な例を見ると役に立つかもしれません。
// Create a new Date for 2015-01-01
var date = new Date(2015,0,1);
// Change the date to 2015-01-02
var x = date.setDate(2);
// The return value from the method is the internal timevalue
console.log(x);
// Check the timevalue
console.log(new Date(x)); // 2 January, 2015
OPはsetDateが元のDateオブジェクトを返すと期待しているようですが、実際には返さず、timevalueを返します。setDateの返り値をDateに変換すれば、元の関数は動作します:
dateinterval[dateinterval.length] = new Date(dateinterval[0].setDate(datointerval[0].getDate() + i));
しかし、それは元のDateオブジェクトを捨てて、新しいものを作成してしまいます。
