在了解此用法之前,一定要了解作用域的概念:
在ES6之前,只有函数作用域和全局作用域,在ES6出现后,就有了块级作用域的概念。
对于刚刚接触 js 的小伙伴来说,可能对以上概念不太重视,但是在我说完之后,你就会了解它的重要性。
在开始之前讲一个例子来说一下作用域的重要性:
if( false ) {
function fun (){
}
}
console.log(fun) // undefined
看到以上代码,小伙伴第一思路, if 中的语句应该没有被执行,打印执行应该报错才对,可是答应的是 ` undefined ` ,说明 if 中的语句中的函数体名称被定义了,此处存在两个知识点:
1. 函数定义提升
2. 作用域问题
无论是函数提升还是变量提升,他们都是发生在对应的 作用域 中,在ES6之前,只有函数作用域和全局作用域,所以无论 if 条件是真是假,fun 都是被定义到全局作用域中,因此打印 undefined
一. var 的用法
1. 变量提升
无论在作用域中哪一步定义,都会位于所在定义域的顶部
function fun (){
console.log(name) // undefined
var name = ' 石头山 '
}
实际执行步骤为:
function fun (){
var name;
console.log(name) // undefined
name = ' 石头山 '
}
2. 可重复定义
var 可定义相同变量名赋值,但最终只保留最后一个值
var name = ' 石头山 ' ;
var name = ' 小鸟 ' ;
console.log(name) // 小鸟
3. 自动存入 window
使用 var 在全局作用域中定义变量,可以使用 全局对象 window 进行访问
var name = ' 石头山 ' ;
console.log(window.name) // 石头山
注:由于 var 使用不严谨,在很多时候造成难以预料的混乱,因此在ES6中提出了 let 和const ,
在代码抒写中尽量不要使用 var,基本全部用 let 和 const 替换它。
二. let 的使用
let 同 var 作用差不多,但是最重要的区别就是,let 声明的范围是块作用域,var 声明的范围是函数作用域。
1. 块级作用域
let 所在区域形成了一个块级作用,它的生命周期只存在于所声明的封闭空间内,而在外部访问不到,使用起来更加安全
if ( true ) {
let name = ' 石头山 ' ;
}
console.log( name ) // error: name 没有被定于
2. 暂时性死区
let 没有变量提升,在 let 声明的作用域中会形成 暂时性死区,意思是在 let 声明的变量所在作用域之前,不可以对其进行访问
var name = '石头山'
if(true) {
console.log(name) // error: Cannot access 'name' before initialization
let name = 'Jack'
}
3. 全局变量
使用 let 声明的全局变量不会成为 全局对象 window 的属性
4. 条件声明
在使用 var 声明变量时,由于声明会被提升,JS 引擎会在作用域顶部合并成为一个,而 let 为块级作用域,所以再声明之后不可再次声明
let name = ' 石头山 ' ;
let name = ' Jock ' ; // error : 报错
三. const 声明
cosnt 同 let 用法基本一直,唯一不同点在于 const 变量在声明时必须初始化,且他的值不可被更改
注:此处不可更改为他的 地址值 指向不可更改
const name = '石头山'
name = 'Jack' // 报错
const obj = {
name: ' 石头山 '
}
obj.name = 'Jack'
console.log(obj.name) // Jack
obj = { // 报错,企图更改其 地址值
name = ' 石头山 ' ;
}
四. 总结
变量提升 | 范围 | 值不可更改 | 可重复声明 | |
var | 是 | 函数作用域 | 否 | 是 |
let | 否 | 块级作用域 | 否 | 否 |
const | 否 | 块级作用域 | 是 | 否 |
最佳实践:
1. 不使用 var
2. 优先使用 const ,let 次之