一、var关键字
1.var声明作用域
var 声明的变量,没有块的概念,可以块访问,不能跨域访问
function test() {
var a = "hello world"; // 局部变量
}
test();
console.log(a); // 报错 a is not defined
2. var声明提升
var在js中是支持预解析的,如下代码不会报错。这是因为使用var声明的变量会自动提升到函数作用域顶部
function foo() {
console.log(age); // undefined
var age = 21;
}
foo();
javaScript引擎,在代码预编译时,javaScript引擎会自动将所有代码里面的var关键字声明的语句都会提升到当前作用域的顶端,如下代码:
function foo() { var age; console.log(age);// 只声明,没赋值 undefined age = 21; } foo();
let 关键字
1.let声明 块作用域
let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问,而var可以跨块访问
2.let 不能重复声明
不允许在同一个块作用域中出现重复声明,如果重复声明会报错
3. let 暂时性死区
let、const与var的另一个重要的区别,let、const声明的变量不会在作用域中被提升。运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区
var temp = 123;
if(true){
temp = 456; // ReferenceError
let temp;
}
4.let 防止变量污染
使用var和let定义for循环中的变量,循环里使用定时器setTimeout后循环结果如下代码:
for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 输出5、5、5、5、5
for (let i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 输出0、1、2、3、4
const 声明
const的行为与let基本相同,唯一一个重要的区别是: const是用来定义常量的,而且定义的时候必须赋值,不赋值会报错,定义之后是不允许被修改的
/ 给常量赋值
const age = 21;
age = 33; // TypeError
// 给对象中的属性赋值
const person = {
name: 'Lili'
};
person.name = '张三';
console.log(person); // {name:'张三'}
这是因为const声明的是栈区里的内容不能修改,基本数据类型的值直接在栈内存中存储,而引用数据类型在栈区保存的是对象在堆区的地址,修改对象的属性,不会修改对象在栈区的地址,如果重新给对象person赋值,则会报错。