第二章 let与const
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
暂时性死区示例,去掉2/3组则无错,第一组改名亦无错。
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 报错
上面代码中,调用bar
函数之所以报错(某些实现可能不报错),是因为参数x
默认值等于另一个参数y
,而此时y
还没有声明,属于”死区“。两句反过来则无事。
function func(arg) {
let arg; // 报错
}
function func(arg) {
{
let arg; // 不报错
}
}
后一个因为涉及到了块级作用域,每个{}包含的都是一个块级作用域,外层作用域无法读取内层作用域的变量,也就是两个arg的作用域是不同的,所以不报错。
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
undefined的原因,是因为在f()里面,tmp要等到if里面才定义,而外部那个tmp,因为函数里面有重名的变量,所以让路了。外面的变量重名的时候,优先级是低于内部的变量的。
const foo = Object.freeze({});
// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;
冻结一个对象,以及冻结一个对象极其所有属性(终极大招啊这是)。
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key, i) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1
let b = 1;
window.b // undefined