JavaScript之关键字声明变量

730 阅读4分钟

首先我们了解下何为关键字:在js里,关键字是有特殊用途,用来表示控制语句的开始和结束,或者执行特定的操作。今天我们来聊聊var、let和const这三个关键字。这三个关键字都可以声明变量,那它们的区别在哪?请往下看

var关键字

var声明作用域

--- 使用var操作符定义的变量会成为包含它的函数的局部变量。比如,使用var在一个函数内部定义一个变量,就意味着该变量会在函数退出时销毁:

function test() {
  var message = "hi";//局部变量
}
test();
console.log(message);//出错

--- 这里报错就是因为var在test函数内部定义了一个message变量并且给它赋值为hi,但是当test函数调用message变量之后随机被销毁,因而无法输出,随即报错。 不妨看看如下代码:

function test() {
  message = "hi";//全局变量
}
test();
console.log(message);//"hi"

--- 这里将var操作符去掉之后,message随即变成全局变量,调用test函数之后,就可以在函数外部访问并输出。

由此我们得到var声明的变量是函数作用域;

var声明提升

--- 来看以下代码:

function foo() {
    console.log(age);
    var age=26;
}
foo();// undefined

--- 没有报错,是因为var age 被提升至函数作用域顶部,即等价于如下代码:

function foo() {
    var age;
    console.log(age);
     age=26;
}
foo();// undefined

--- 这就是提升(host),就是var声明变量会被拉到函数作用域的顶部。

由此我们得到var声明变量会提前到文件最开始的地方,但是初始化还是在语句位置。

let声明

let与var的区别在于let声明的是块作用域,而var声明的范围是函数作用域。

if(true){
    var name = 'li'
    console.log(name);//li
}
console.log(name);//li
if(true){
    let age =26;
    console.log(age);//26
}
console.log(age);//age 未定义

--- 通过对比这两段代码就能很清晰的看出var和let之间的区别,name可以在if块外部被引用,但是age却不能在if块外部被引用,就是因为age的作用域仅限于该块内部,无法被调用。

let也不允许同一个块作用域中出现冗杂声明,这也是我们在日常编程中需要注意的问题。

var name;
var name;
let age;
let age;//age has already been declared

暂时性死区

let与var的另一个重要区别是let声明的变量不会在作用域中被提升

//name 会被提升
console.log(name)//undefined
var name = 'li'; 
//age 不会被提升
console.log(age)//age未定义
let age =26;

--- 只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

全局声明

使用let在全局作用域中声明的变量不会成为window对象的属性,而var声明的对象则会

var name = 'li';
console.log(window.name);//li
let age = 26;
console.log(window.age);//undefined

for循环中的let声明

--- 我们先来看看两段代码

for(var i = 0; i < 5; ++i){
     //循环逻辑
 }
console.log(i)//5 
for(let i = 0; i < 5; ++i){
    //循环逻辑
 }
console.log(i);//i没有定义

--- 使用var的时候,for循环定义的迭代变量会渗透到循环体外部,但使用let之后,这个问题就消失了,因为作用域仅仅局限于for循环块内部。 我们再来看下有意思的事情

for(var i = 0; i < 5; ++i){
    setTimeout(()=>console.log(i),0)
}//5,5,5,5,5

for(let i = 0; i < 5; ++i){
    setTimeout(()=>console.log(i),0)
}//0,1,2,3,4

--- 第一段代码之所以会出现的情况,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5,在之后执行的逻辑中,所有的i都是同一个变量,因此都输出5。而第二段代码中,js在执行过程中为每个迭代循环声明一个新的变量,因此循环过程中会执行每个迭代变量的值。

const声明

--- const与let大体相同,唯一一个重要区别是它声明变量时必须同时初始化变量,且修改const声明的变量会报错。

const age = 26;
age = 36// TypeError

总结

var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。

let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。

const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。同一个变量只能使用一种方式声明,不然会报错

--- 以上就是我对js三个关键字的一点拙见,未完待续........