1.变量提升:var会发生变量提升,let和const不存在变量提升
2.暂时性死区:变量声明之前变量不可用称为暂时性死区。var不存在,let和const存在暂时性死区
3.typeof 不再是百分百不会报错:let声明前不能使用typeof
typeof x; // Uncaught ReferenceError: Cannot access 'x' before initialization
let x;
4.不允许重复声明:var重复声明会覆盖前一个,let和const不允许重复声明(用var声明过的也不允许let和const声明)
5.函数内部:var声明过的也不允许let和const声明,有形参后,不能再使用let声明
// 函数内部
function get(){
var b =1;
let b =6;
}
function get(b){
let b
}
ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景
第一种场景,内层变量可能会覆盖外层变量。
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}}
f(); // undefined
第二种场景,用来计数的循环变量泄露为全局变量for (var i = 0; i < s.length; i++){}
每一层都是一个单独的作用域。每一层中的数据是不互通的。(里面可以访问外面的,外面不可以访问里面的)
{
{
let a = 123;
}
console.log(a) // 報錯
}
// 里面可以访问外层的a
{
{
let a = 123;
{
console.log(a)
}
}
}
let a = '全局';
{
let a = '局部'
console.log(a);
}
console.log(a);
var aa = '全局';
(function(){
var aa = '局部'
console.log(aa);
})()
console.log(aa);
1. const声明一个只读的常量。一旦声明,常量的值就不能改变
2. const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值
3.内存地址不变 里面的东西可以边
const foo = {};
// 为 foo 添加一个属性,可以成功foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only
常量foo指向一个冻结的对象,所以添加新属性不起作用,严格模式时还会报错。
const foo = Object.freeze({});
// 常规模式时,下面一行不起作用;// 严格模式时,该行会报错
foo.prop = 123;
'use strict';
const foo = Object.freeze({});
foo.prop = 123; // 報錯
for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
这种for循环和循环体内使用的是用一个变量,所以最后输出的是6
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};}
a[6](); // 6
以下这种,for循环和循环体内都由单独的作用域变量,所以每次输出的都是自己作用域的变量‘abc’
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc// abc// abc