let const var
前言: let, const,var在我们的代码中是很常见的,但总是对它有一点模模糊糊的,像在我面前隔了一层面纱。最近看了多篇文章,小小的总结了一下,希望自己能搞懂它,也希望对各位有所帮助。(文中的例子都是经过vscode验证过的)
1. 变量提升:
1.1 作用域角度
从作用域来说,这三个都是有变量提升的。执行一段代码时,作用域是优先所有变量建立起来的,所以它在建立的时候就会看看自己内部有什么变量。
-
var :有变量提升
console.log(aa); // undefined var aa = '22' -
let:下面这个例子可以证明它是有变量提升的。
let a = '1' { console.log(a); //ReferenceError: Cannot access 'a' before initialization let a = '2' } let a = 1 { console.log(a); //1 }如果
let没有被提升的话,那么a打印出来的值应该是外部 a 的值 1 ,而这里却是报错(错误信息意思:在a没有初始化之前不能访问)。 -
const 和
let一样,通过下面例子也可以说它是由变量提升的
const b = '1'
{
console.log(b);
// ReferenceError: Cannot access 'b' before initialization
const b = '3'
}
1.2 代码执行角度
从代码执行这个角度来说,let,const是没有变量提升的。就是常说的,在声明之前var可以被访问,而let,const不能。
总结下let,const,var和函数的创建过程:
- let,const是【创建】提升
- var是【创建】提升,【初始化】提升
- fn 是【创建】提升,【初始化】提升,【赋值】提升
下面就详细说说他们的创建过程:
-
let,const:({let a = 1})- 在一个作用域{}里,找到所有用
let,const声明的变量,在环境中【创建】这些变量。 - 开始执行(注意,没有初始化哦),所以引用它的时候会报错。
- 再【初始化】为1。如果是
let a,那么就初始化为undefined。(注意这不是赋值哦)
- 在一个作用域{}里,找到所有用
-
var:{var a = 1}
-
在一个作用域{}里,找到所有用
var声明的变量,在环境中【创建】这些变量。(和上面一样) -
将这些变量【初始化】为undefined。
-
开始执行代码
-
将 a变量 【赋值】为 1
就是说,
var会在代码执行之前就已经完成了【创建】和【初始化】这两个过程 -
-
fn:
- 找到所有用
function声明的变量,在环境中【创建】这些变量 - 将这些变量【初始化】并【赋值】为 函数体
- 开始执行
- 找到所有用
就是说,fn在代码执行之前就完成了,创建,初始化,赋值这三个步骤。所以可以在fn代码前调用它。
fn() // hello
function fn(){
console.log('hello')
}
2. 它们值能不能改变?
2.1 var
var声明的变量值是可以改变的,而且可以重复声明。后面的变量名会覆盖前面的相同变量名。
var a = 1
console.log(a); //1
a = 2
console.log(a); //2
var a = 3
console.log(a); //3
2.2 let
let不可以重复声明,但是可以重新赋值
let a = 3
console.log(a); //3
a=4
console.log(a); //4
let a = 5
console.log(a);
//SyntaxError: Identifier 'a' has already been declared
2.3 const
const :不可以重复声明,简单类型的变量值不可以重新赋值,但是复杂类型(对象内的属性)内部的变量可以
const a = 2
console.log(a); //2
a = 3
console.log(a);
// TypeError: Assignment to constant variable.
const a = {
d:1,
dd:false
}
console.log(a.dd); //false
a.dd = true
console.log(a.dd); //true
3.扩展:为什么全局对象可以访问到var变量,却不能访问到let和const变量?
回答:
因为,var声明的对象是挂载在全局对象上的,存放在global作用域中。但是let ,const声明的变量是放在别的作用域里面的,所以 window全局对象是访问不到的。例子:
(在HTML中)
<body>
<script>
var a = 12
let aaaa = 3
function fn(){
let b = 12
const d = 0
}
console.log(fn.prototype);
</script>
</body>
上面的例子显示,
let声明的变量 aaa是存放在 Script作用域的。