一、问题的提出
在学习js的过程中,很多小伙伴会了解变量的知识点。其实每个变量只是更好的表达数据的占位符。在ECMAScript中,有三个关键字可以声明变量:var,const和let。
但是为什么简简单单的声明变量还需要三个关键字呢?他们有什么异同呢?
二、出现时间的不同
通过查询资料我们发现,let、const两个变量只能在ES6以及更晚的版本中使用,var在ES的所有版本中均可使用。个人理解为let和const两个变量是对于var缺点的补充。
三、三者区别
节约时间,先说结果再说原因!!
var
全局作用域、函数作用域。
同一作用域下,可以多次声明同一变量(可以在后续代码中重新赋值)。
可以在声明前调用(先调用后声明)。
let
作用域:全局作用域、函数作用域、块级作用域。
同一作用域下,不可以多次声明同一变量。
不可以在声明前调用。
const
作用域:全局作用域、函数作用域、块级作用域。
同一作用域下,不可以多次声明同一变量。
不可以在声明前调用。
由此可见
const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且
尝试修改 const 声明的变量会导致运行时错误。而var只能用于全局作用域和函数作用域。
刚刚提到了一个名词叫块级作用域,指的范围是:
循环
判断
同一级{ }里面的东西
下面我们来详解一下这些关键字吧~~
四、详解关键字
var关键字
1.1 var关键字
此处是对于var的函数作用域的展示,在方法中声明的var变量,只对于该方法内部起到效果。
function Test() {
var a = "hi"; // 局部变量
}
test();
console.log(a); // 出错!
解决此类问题,可以抹去var变量,直接定义一个全局变量如下 ,不过一般不推荐这么做,会造成困惑,维护起来也麻烦。
function test() {
a = "hello world"; // 局部变量
}
test();
console.log(a); // "hello world"
1.2 var声明的提升
这一条看起来就很诡异,在作用域内先输出变量,再定义的形式,在Js中不会报错,因为声明的变量会自动提到函数作用域顶部
举个例子:
function foo() {
console.log(score);
var score = 26;
}
foo(); // undefined
这个代码中,先输出了score,之后才进行赋值 。
这里是因为在ES运行时,会自动把所有关键字var声明的变量放在顶部。但是此时未赋值。所以输出undefined。在处理的过程中,ES把上述代码等同于:
var score;
console.log(score);
score = 26;
}
foo(); // undefined
这就是var的声明提升
let关键字
1.let关键字的作用域
说到let,不可避免的一定要提到块级作用域,前文中提到,可以近似的理解为统一对{ }里面的内容。
写个代码跑跑看吧
//首先我们可以先写个var,对比一下
if(true){
var name = "xiaotian"
console.log(name) //"xiaotian"
}
console.log(name) //"xiaotian"
//如果此时用的是let呢?
if(true){
let name = "xiaotian"
console.log(name) //"xiaotian"
}
console.log(name) //ReferenceError.age没有定义
由此可见,let只在代码的作用域内起到作用。 而var可以在全局起到作用。值得注意的是,这里用到的是if语句,并非上文中提到的函数作用域function()。所以var定义的数值可以传出。
值得注意的是let和var不同的作用域,即函数嵌套使用,可以重复定义let和var。
2.声明范围
var会成为windows对象的属性,但是let不会
3.条件
前文提到,var声明的变量可以被提升,在顶部定义。但let只作用于块作用域,无法检查是否已经使用过let声明相同变量。同样也不能在声明前被调用。
const关键词
这个关键字和let用法很相似 ,但是循环过程中有一种报错形式,此处时因为迭代变量会自增:
for (const i = 0; i < 10; ++i) {} // TypeError:给常量赋值
综上所述
var因为作用域太过于广泛,容易在使用过程中出现问题,let和const会好很多,也更易于定位错误。