let命名
- 所声明的变量只在命令所在的代码块内有效
{
let a = 1;
var b = 2;
console.log(a) // 1
console.log(b) // 2
}
console.log(a) // a is not defined
console.log(b) // 2
- 使用let声明的命令变量在域解析的时候不会被提升
{
console.log(b); // b is not defined
let b = 2;
}
{
let f = 10;
function fn(){
f = 7;
let f = 2; // 暂时性死区
}
fn();
}
- let不允许在同一个作用域下声明已经存在的变量
{
let a = 1;
let a = 2; //报错 'a' has already been declared
}
- let在循环中应用
for ( let i = 0; i < btns.length; i++){
btns[i].onclick = function(){
console.log(i) //0,1,2,3,4....
//在这里,let与var的区别是:let只是在循环之中的,而var在整个函数之中
}
}
console.log(i) // i is not defined
var a = [];
for ( var i = 0 ; i< 10 ; i ++){
a[i] = function(){
console.log(i)
}
}
a[6](); // 10
var b = [];
for ( let i = 0; i < 10; i ++){
b[i] = function(){
console.log(i)
}
}
b[6](); // 6
- 暂时性死区 使用let命令声明变量之前,该变量不能使用
var tmp = 123;
if ( true){
tmp = 'abc'; // tmp is not defined
let tmp; // 在这个代码块中定义了tmp
}
let tmp2 = 123;
if (true){
tmp2 = 'abc';
console.log(tmp2)
}
console.log(tmp2)
块级作用域
-
为什么需要块级作用域
- 内层变量可能会覆盖外层变量
var tmp = new Date(); function f(){ console.log(tmp); if (false){ var tmp = "hello" } } f(); // undefined
- 用来计数的循环变量泄露为全局变量
-
ES6 的块级作用域
- 外层作用块不受内层作用块的影响
function f(){ let n = 5; if ( true){ n = 10 } console.lo(n) // 5 外层作用块不受内层作用块的影响 }
- 外层作用域无法访问内层作用域的变量
{let now = '1213'} console.log(now) // now is not defined
- 内层作用域可以定义外层作用域相同的变量
{{ let name = 'dan' { let name = 'xxi' } }}
- 立即执行的匿名函数(IIFE)不再有必要
/*(function(){ console.log('asdklfj'); document.body.backgroundColor = '#f5f5f5'; })()*/ { console.log('jaflkajsd'); }
- 内部声明的函数不会影响到外部声明
{ let a = 'secret'; function f(){ return a } } f() //报错 let f; let b = 'bbb' { let a = 'dan'; f = function(){ return a; } console.log(b); // 内层作用块还是可以拿到外层作用块的内容 } console.log(f());
const命名
- const 声明的变量一旦声明,其值就不能发生改变,一旦声明常量,就必须初始化,不能留到以后赋值
const PI = 3.1415;
PI = 3; // 报错
声明的常量只在其所在的代码块内有效,
声明的常量不会被提升,同样有暂时性死区,只能在声明后使用
不能声明已经声明过的常量或者变量
注:
- 声明的时候必须赋值
- 声明的常量储存简单的数据类型是不可改变其值,如果储存的是对象,那么引用不可改变,至于对象里数据怎么改变是没有关系的
const obj = { a: 10};
obj.a = 20;
console.log(obj) // {a: 20}
const a = [];
a.push('hello'); // 可以执行
a.length = 0; // 可以执行
a = ["dan"] // 报错
- 如果想将对象冻结,使用Object.freeze({});
const foo = Object.freeze({});
foo.prop = 123; // 不起作用
console.log(foo.prop) // undefined
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach((key,value) => {
if ( typeof obj[key] === 'object'){
constantize(obj[key])
}
})
}