Open KeihakuOh opened 2 months ago
varとlet
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 0);
}
var の特徴:
var は関数スコープです。つまり、ループの中でiを宣言しても、ループが終わった後でも同じ変数iを共有しています。 このため、ループが完了した後に、iは3になっています。 動作:
setTimeoutで非同期処理が登録されますが、全てのsetTimeoutが実行されるのは、ループが完了した後です。 ループが完了した時点で、iは3になっているため、全てのsetTimeoutのコールバックが実行される時点では、iは3です。 結果: 3, 3, 3
ここで、全ての setTimeout のコールバックが実行されるが、すべて同じ i(3)を参照しているため、3, 3, 3 と出力される。
ーーーーー
for (let i = 1; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 0);
}
let の特徴:
let はブロックスコープです。つまり、ループごとに新しいiが作成され、各ループのスコープ内で独立して存在します。 そのため、setTimeoutのコールバック関数の中では、それぞれのループでのiの値が保持されています。 動作:
setTimeoutのコールバックが実行される時、ループごとに異なるiの値が保持されています。 最初のiが1、次が2です。 結果: 1, 2
実行の詳細な流れ i = 0 で 新しいスコープが作成され、setTimeout が登録されます。このコールバックは i = 0 を保持しています。 i = 1 でまた別の新しいスコープが作られ、setTimeout が登録されます。このコールバックは i = 1 を保持しています。 i = 2 でも同様に、別の新しいスコープが作られ、setTimeout が登録されます。このコールバックは i = 2 を保持しています。 ループが完了すると、各 setTimeout が順に実行され、それぞれ異なる i の値を出力します。
ーーーーー
ブロックスコープ(let、const)
if (true) {
let x = 10; // `let` はブロックスコープ内でのみ有効
console.log(x); // 10
}
console.log(x); // エラー: `x` はブロックの外では定義されていない
//let はブロックスコープなので、ifブロック内でのみxが有効です。
関数スコープ(var)
function example() {
if (true) {
var y = 20; // `var` は関数スコープ内で有効
console.log(y); // 20
}
console.log(y); // 20: 関数全体で `y` は有効
}
example();
var は関数スコープなので、ifブロックの外でも関数内で有効です。
fields: () => ({ ... }) とすることで、フィールドの定義を遅延評価し、相互依存する型同士の参照問題を回避できます。 型が相互に依存している場合(今回のUserTypeとCompanyTypeのようなケース)、フィールドの定義を関数でラップすることで、依存関係が適切に解決されます。
下のようにするとuserTypeは未定義というエラーは出てこない