1, 声明提升
console.log(num) // undefined
var num = 100
2, 变量覆盖
var num1 = 100
var num1 = 200
conosle.log(num1) // 200
3, 没有块级作用域
function fn() {
for (var i = 0; i <= 5; i++) {
console.log(i) // 0 1 2 3 4 5
}
console.log(i) // 6
}
fn()
1, let 声明的变量具有块级作用域的特征
function fn() {
let a = 10
}
console.log(a) // a is not defined
2, 在同一个块级作用域,不能重复声明变量
function fn() {
let a = 10
let a = 20
}
console.log(a) // Identifier 'a' has already been declared
3, let 声明的变量不存在变量提升,换种说法就是let声明存在暂时性死区(TDZ)
console.log(num) // Cannot access 'num' before initialization
let num = 10
1, const 声明的变量具有块级作用域的特征
function fn() {
const a = 10
}
console.log(a) // a is not defined
2, 在同一个块级作用域,不能重复声明变量
function fn() {
const a = 10
const a = 20
}
console.log(a) // Identifier 'a' has already been declared
3, const 声明的变量不存在变量提升,换种说法就是const声明存在暂时性死区(TDZ)
console.log(num) // Cannot access 'num' before initialization
const num = 10
4, const 声明一旦定义后,不能修改
const num = 100
num = 200
console.log(num) // Assignment to constant variable.
ES5中作用域有:全局作用域、函数作用域,没有块级作用域的概念。
ES6新增了块级作用域,由 {} 包括,if 语句和 for 语句里面的 {} 都属于块作用域
{
var num = 100
console.log(num) // 100
}
console.log(num) // 100 可见,通过var定义的变量可以跨块作用域访问到
function fn() {
var num = 100
console.log(num) // 100
}
console.log(num) // num is not defined 可见,通过var定义的变量不能跨函数作用域访问到
if (true) {
var num = 100
}
console.log(num) // 100
for (var i = 0; i <= 5; i++) {
var num = 100
}
console.log(i) // 6
console.log(num) // 100
if 语句和 for 语句中用 var 定义的变量可以在外面访问到,可见,if 语句和 for 语句属于块级作用域,不属于函数作用域
// 块级作用域
{
var a = 100
var b = 200
var c = 300
var a1
let b1
// const c1
console.log(a) // 100
console.log(b) // 200
console.log(c) // 300
console.log(a1) // undefined
console.log(b1) // undefined
}
console.log(a) // 100
console.log(b) // 200
console.log(c) // 300
// 函数作用域
(function fn() {
var a = 100
let b = 200
const c = 300
console.log(a) // 100
console.log(b) // 200
console.log(c) // 300
})()
console.log(a) // a is not defined
console.log(b) // b is not defined
console.log(c) // c is not defined
const 定义的基本类型不能改变,但是定义的对象是可以通过修改对象属性等方法改变的
const num = 100
num = 200
console.log(num) // Assignment to constant variable.
const person = {
name: 'Tom',
age: 18
}
person = {
name: 'Jerry',
age: 20
}
console.log(person) // Assignment to constant variable.
const person = {
name: 'Tom',
age: 18
}
person.name = 'Jerry'
console.log(person) // {name: 'Jerry', age: 18}
基本数据类型的变量保存在栈区中,基本数据类型的值直接在栈内存中存储,值与值之间是独立存在的,修改一个变量不会影响其他的变量。
引用数据类型的值是同时保存在栈内存和堆内存的对象,栈区保存了对象在堆区的地址。
const 声明的 person 给属性重新赋值是可以的,但是给 person 重新赋值是不可以的,那样会改变 person 在栈区的地址
for (var i = 0; i <= 5; i++) {
setTimeout(function() {
console.log(i)
}, 1000)
}
console.log(i)
setTimeout 是异步执行的,1000ms后向任务队列里添加一个任务,只有主线程的全部执行完才会执行任务队列里的任务,所以当主线程 for 循环执行完之后 i 的值为 6, 这时候再去执行任务队列里执行任务, i 全部是 6。
每次 for 循环的时候 setTimeout 都会执行,但是里面的 function 则不会执行被放入任务队列,因此放了 6 次, for 循环的 6 次执行完之后不到 1000ms, 100ms后全部执行任务队列里的函数,所以输出 6 个 6。
for (let i = 0; i <= 5; i++) {
setTimeout(function() {
console.log(i)
}, 1000)
}
console.log(i)
let定义的 i 事块级作用域,每个 i 只能存活到大括号结束,并不会把后面的 for 循环的 i 值赋给前面的 setTimeout 中的 i,而var 定义的 i是局部变量,这个 i 的生命周期不受for 循环的大括号限制。