let命令
局部有效性
ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。什么意思呢?下面我来详细介绍一下。
var
for (var b=0; b<10; b++){
console.log(b)
}
console.log(b)
let
for (let b=0; b<10; b++){
console.log(b)
}
console.log(b)
两段代码看上去只是定义变量的方式上有差异,但实则区别很大。执行完代码后 var 在循环外输出的结果是 10
,而 let 输出的结果为 Uncaught ReferenceError: b is not defined
。
=> 这是因为let 定义的 b只在 for 循环内部起作用,在外部是引用不到 变量 b。
不能重复定义
function index(){
let b = 10;
let b = 20; // Error: Identifier 'b' has already been declared
// 即b已经定义
}
for(let b=0; b<10; b++){ //父级作用域
//子代作用域 => 就近原则
let b = 'wrong'
console.log(b)
}
这是 for 循环的一个特点,不论是 var 还是 let,设置循环变量
和循环内设置变量
其实是两件事,这里可能会引出歧义,不是不能重复定义吗? => 要注意的是不能重复定义的条件是在同一作用域下,而设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
不存在变量提升
var b = 10;
console.log(b) // => 10
console.log(b) // => undefined
var b = 10
变量提升就是在JS 预解析机制
中,首先识别 var
声明的参数,并赋值给 undefined, 然后再寻找 带有关键词 function
的函数。解析完后,再按从上到下
的顺序执行JS代码,在未赋值实值 10
情况下,在控制打印的就是 undefined。
区别于var ,let 方法声明的参数不具备这样的特点。
console.log(b) // => Error: Cannot access 'b' before initialization
// 也就是不能够识别 b
var b = 10
暂时性死区
=> 只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
var d = 'abc'
if(true){
d = 'cde'
var d = 1
console.log(d) // => 1
}
var d = 'abc'
if(true){
d = 'cde' // ReferenceError:Cannot access 'd' before initialization
// b 不能够别识别
let d = 1
console.log(d)
}
虽然外面已经定义了全局变量 d,但是在某一区域内仍然不能够改变 let方法先定义后使用
的原则,所以我们可以通俗的理解为:在代码块内,只要用 let 方法定义变量,不管外部有没有全局变量,就必须先定义再使用。
const 命令
基本用法
const
声明一个只读的常量。一旦声明,常量的值就不能改变。- const声明的常量,不可重复声明
const
一旦声明变量,就必须立即初始化,不能留到以后赋值。(这是一个比较重要的地方
)cons
t的作用域与let
命令相同:只在声明所在的块级作用域内有效。const
命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
看完了一些基本用法, 可能会有一些疑惑,JS 的数据类型分为 基本数据类型 和引用数据类型,是否这两种数据类型的变量值都不允许更改?
// 基本数据类型 => 数值,字符串,布尔值
const a = 'javascript',
b = 100,
c = true;
//此时不能随便更改 a,b,c的值
--------------------------------------
// 引用数据类型 => 数组,对象
const a1 = [1, 2, 3]
b2 = {
name : 'Jack',
age : 18
}
//因为变量对引用数据类型来说,是指向他们在堆空间的存储的地址,所以地址是不能改变
//不能再用 a = [.......] 方法给 a赋值,只能通过数组的一些方法给原有的数组添加或者删除值。
//对象也一样