let与const
let
也是用来声明变量,但是不同于var,个人理解是它是用来修复var的一些神奇效果,似的变量更加规范,简单来说let定义的变量就是私有变量,有以下几点作用
- let声明的变量只在它所在的代码块中生效(即它的块级作用域中生效)
if (true) { let i; console.log(i);}//console.log(i); ReferenceError: i is not defined
- 对于for循环的块级作用域,当let声明循环体i时,有两个特点
-
let声明的i外部不能被访问
for (let i = 0; i < 4; i ++) { console.log(i); }console.log(i); //i is not defined
之所以里面能访问i,因为for循环子作用域能访问外部作用
-
for循环当在子作用域,声明let i时与循环体i是独立的
for (let i = 0; i < 4; i ++) { let i = 6; console.log(i); }
为什么能,简单说就是i私有了
-
每次循环let都是重新申明的,正因为这样,就能解决for循环时闭包带来的问题
for (let i = 0; i < 4; i ++) { setTimeout(function () {console.log(i)}, 100) }//0 1 2 3for (var i = 0; i < 4; i ++) { setTimeout(function () {console.log(i)}, 100) }//4 4 4 4
-
不存在变量提升,
//console.log(i);//console.log(typeof i);let i;
都是会报错的,i is not defined。
对于let声明的变量,typeof 不再是安全形式了,并且该变量必须在声明后才能使用,在它之前使用那就是暂时的死区function f(x=y,y=2) {};f(); //y is not definedlet x = x; //x is not defined
-
同一作用域中也不能重复定义
let i;let i; //报错
function f(n) { let n}f(); //报错
不同作用域可以重复且各自独立
function f(n) { {let n}}
-
let声明的变量不属于window
let i = 1;console.log(window.i); //undefined
const作用是用来声明常量
作用和let一样,但多两点
-
一旦声明必须初始化,也就是必需赋值,否则报错;
const P = 1;
-
一旦赋值不能被改变,其本质是不能改变变量的内存地址
变量是原始类型的数据,其本身就是不可变的,再加上不能重新赋值,改变地址const P = 1;P = 2; //报错
变量是对象类型的,其本身是可变的,所以也就能改变,要注意的是其地址并不改变
const P = {a : 1} ;P.a =2;console.log(P); //{a : 2}
想要其内容也不变,可以冻结它
const P = {a : 1} ;Object.freeze(P);P.a =2;console.log(P);