Var Hoisting
`var` is function-scoped and hoisted: the binding exists for the whole function, and on a path where its declaration never ran it holds a real `undefined` — not its type's zero value. TypeScript keeps the declared type (`number`, `string`, …); the value is what Node produces.
function pick(cond: boolean) {
if (cond) {
var n = 42;
var s = "hello";
var o = { x: 1 };
var xs = [1, 2, 3];
}
console.log(n, s, o, xs); // 42 hello { x: 1 } [ 1, 2, 3 ] / undefined ×4
console.log(typeof n, typeof s, typeof o, typeof xs); // number string object object / undefined ×4
if (n !== undefined) console.log("narrowed", n + 1); // narrowed 43 / (nothing)
return n; // 42 / undefined
}
console.log(pick(true));
console.log(pick(false));
// Dead code after a `break` still declares its `var`s.
do { var a = 1; break; var b = "never"; } while (0);
console.log(a, b, typeof b); // 1 undefined undefined
// A `for` init `var` runs whenever the loop does; a body `var` leaks out too.
for (var i = 0; i < 3; i++) { var last = i * 10; }
console.log(i, last); // 3 20
// A module-level `var` inside a block is a module binding: a function
// reads it, undefined until (and unless) its declaration runs.
if (Math.random() > 2) { var never = "set"; }
for (let k = 0; k < 3; k++) { var seen = k; }
function readBoth() { return [never, seen]; }
console.log(readBoth()); // [ undefined, 2 ]
// A local written inside a `try` keeps its value after a throw.
let count = 0;
try { count = 1; throw new Error("boom"); } catch (e) { console.log("caught with count =", count); } // 1
console.log(count); // 1
// Unary + is ToNumber, exactly like Number().
// (TypeScript rejects a bare `+null`; a value typed any reaches it.)
const nothing: any = null, missing: any = undefined;
console.log(+" 12 ", +"0x10", +"junk", +true, +nothing, +missing, +[], +[5]); // 12 16 NaN 1 0 NaN 0 5View source on GitHubexamples/basics/var_hoisting.ts