varletconst声明方式的区别

Posted 慕斯蛋糕

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了varletconst声明方式的区别相关的知识,希望对你有一定的参考价值。

-----  let 和 const的使用规则基本相同,有以下2点区别  -----
1、const声明和赋值必须同时完成
const a   // 报语法错误:常量声明中缺少初始值设定项
------------------------------------------------------------------------
2、const声明的变量不能重新赋值【如果声明来存储基础数据类型,可以称为常量,对象/函数个人理解还是叫变量】
const num = 10
num = 20    // 报语法错误:赋值给常量变量
------------------------------------------------------------------------
3、【扩展】当使用const声明一个不会变的数据时,变量名可以使用全大写,声明对象/函数时常规的变量名就好
const PI = 3.14
const obj = name: \'lyh\', age: 27
const fn = function fn()
 
4、【应用】实际开发中在不需要给变量重新赋值的情况下,建议优先使用const,这样可以避免对象/函数被意外修改
------------------------------------------------------------------------
-----  let/const 和 var的区别  -----
1、重复声明:var可以重复声明一个已经存在的变量;let不允许声明一个已经存在的变量(不论是let、const还是var声明的)
var a = 10
var a = 20
console.log(a) // 20  
let a = 30  // 报语法错误:标识符“a”已声明
------------------------------------------------------------------------
2、变量提升:var声明的变量会提升到当前作用域的顶部,赋值前访问变量得到undefined;let声明的变量不会提升,不允许在声明前访问变量
console.log(a)  // undefined
var a = 10
console.log(a) // 10
console.log(b) // 报语法错误:初始化前无法访问“b”
let b = 20
console.log(b) // 20 要注释上面那一行打印才能正常执行这一句
------------------------------------------------------------------------
3、作用域:var声明的变量只会有全局作用域和函数作用域,let声明的变量还会有块作用域
-----例1:var声明的变量具有函数作用域
console.log(a)  //  报语法错误:a is not defined
function fn()
  console.log(a)  // undefiend  由于var声明的变量具有函数作用域,所以a只会提升到函数内部的顶部
  var a = 10
  console.log(a)  // 10
fn()
console.log(a)  //  报语法错误:a is not defined
-----例2:var声明的变量没有块级作用域
// var声明的变量没有块级作用域,在块内声明可以在块外访问,变量的声明会提升到全局作用域顶部
console.log(b)  // undefined  
  console.log(b)  // undefined
  var b = 20
  console.log(b)  // 20
console.log(b)  // 20
-----例3:let声明的变量会产生块级作用域
  let c = 30
  console.log(c)  // 30
console.log(c)  // 报语法错误:c is not defined
------------------------------------------------------------------------
4、【拓展】通过debugger可以看到var声明的变量存在执行栈的Global中(全局对象GO Global Object/在浏览器中也叫window对象)let声明的变量存在Script中(全局变量对象)
debugger
var a = 10
let b = 20
console.log(window.a)   // 10  全局作用域下,var声明的变量默认变成window的一个属性
console.log(window.b)   // undefined  let声明的变量不会绑定到window上

 

JavaScript 各声明varletconst方式区别『详解』

JavaScript 变量声明三种方式的区别『var、let、const』

文章目录


一、变量声明

变量的声明在每个编程语言里都会有,JavaScript的变量声明有varlet,常量的声明是const。这几种声明方式的作用域有一定差别,以var举例,以var声明的变量会被隐式地创建为全局变量,并且还会产生变量提升的效果。


二、变量提升🎈

在讲解 varletconst 之前应了解什么是变量提升,这很重要。

先来看看这几行代码,判断是否能够正确打印不抛出异常

 // 代码片段一
 a = 1;
 console.log(a);	// 打印:1

 // 代码片段二
 var a = 1;
 console.log(a)		// 打印:1

 // 代码片段三
 console.log(a)		// 打印:undefined
 var a = 1;

 // 代码片段四
 console.log(a)		// 抛出异常

 // 代码片段五
 var a = 1;
 
     console.log(a)	// 打印:1
 

 // 代码片段六
 console.log(a)		// 打印:undefined
 
     var a = 1;
     console.log(a)	// 打印:1
 
  • 代码片段一: 即使没有使用声明符也能正常赋值和输出,这是因为在解析JavaScript代码的时候,将变量提前以var的方式进行了声明。
  • 代码片段二: 正常以var进行声明的方式,结果当然能输出。
  • 代码片段三: 神奇的是,程序也能正常输出并且不会抛出异常,但输出结果为undefined,这印证了在代码片段一中所说的,将变量提前以var的方式进行了声明。
  • 代码片段四: 二话不说总结打印一个为定义的变量时,那就不存在提前声明了,会抛出 ReferenceError异常。
  • 代码片段五: 对于块级代码块,能够调用全局的声明。
  • 代码片段六: 即使 var 声明变量写在了块里,变量依旧可以在声明之前使用,存在变量提升的现象。

再来看看其他声明方式的效果

 // let 声明变量
 console.log(a);
 let a = 1;
 console.log(a);

 // const 声明变量
 const a = 1;
 console.log(a);

以这两种方式声明,在声明之前调用变量会抛出 ReferenceError 异常,只有在声明之后调用不会异常,可见这两种方式是不存在变量提示的。

总结

  • varfunction 在作用域内 存在着变量提升。
  • 变量提升将影响变量声明,而不会影响其值的初始化,在赋值之前,值为undefined
  • function的变量提升能够使函数在声明前能够被调用。
  • letconst这两种声明变量的方式不会造成变量提升。

三、var 变量声明

var 声明一个变量,可同时将其初始化为一个值,它是一个全局作用域的声明方式,也被函数作用域限制。但因其全局作用,以及提前声明的特性,容易造成变量的全局污染,造成意想不到的后果。

1、声明一个变量

// 声明一个变量
var a;

2、声明并初始化一个变量

// 声明并初始化一个变量
var a = 1;

3、声明并初始化两个个变量

// 声明并初始化两个个变量
var a = 1, b = 2;

4、多个变量的初始化

// 多个变量的初始化
var a;
function f() 
    var a = b = 1

f()
console.log(a)      // 打印:undefined
console.log(b)      // 打印:1

在函数里以var a = b = 值的方式将变量ab同时赋值为了1,这种操作等用于var a = 1; b = 1。但调用函数后,函数外打印打印这两个值时能正确执行值不相等

  • a、先来讲讲为什么说能正确执行,b 变量只在函数中出现过,根据局部能调用全局作用域,全局不能调用局部作用域的特点,b 应该会抛出未定义的异常才对,但实际上并没有这样。这是因为在函数内部初始化变量b的时候,并未指定声明符,那么JavaScript将变量提前以var的方式进行了声明,而这个提升是全局的。
  • b、 再来说说为什么 a != b,其实很简单,在程序最开始就声明了变量var a,而执行函数时并没有将a的值修改为1,这是因为被函数作用域所限制,1这个值只在函数中生效。

5、意想不到的全局污染

for (var i = 1; i <= 10; i++) 
    // 延时一秒后执行
    setTimeout(function () 
        console.log(i);		// 输出十次11
    , 1000)

var变量在使用循环时搭配定时器,会产生意想不到的效果,程序的目的是在一秒之后分别输出1-10的值,结果却是输出十次11。var 改成 let则恢复正常

var x = 1;

function func1() 
    var y = 2;

    function func2() 
        x = 4;
        y = 5
        z = 6;
    

    func2()
    console.log(x, y, z)	// 打印:4, 5, 6


func1()
console.log(x)				// 打印:4

上述代码,xyz打印的值各是多少呢?将xyz分开来看。

  • 对于x来说它是写在所有函数之前的全局变量,对x的修改是全局的,x的最后一次修改是在func2函数里,那么x的值到最后应该为4。
  • 对于y来说,是在func1函数中声明的,那么其作用域只在func1函数中生效,y的最后一次修改是在func2函数里,那么y的值到最后应该为5。
  • z的值只出现过一次赋值,在此之前并没有任何的变量声明,在func2函数中以z = 5表达式赋值为5,其写法相同于var z = 5,那么z的值到最后应该为6。

6、可重复声明

 // 重复声明
 var a = 1;
 var a = 2;
 console.log(a)      // 打印最后赋的值:2

 // 循环重复声明
 var x;
 for (var i=1; i <= 5; i++) 
     var x = i;
 
 console.log(x)      // 打印最后赋的值:5

使用var声明变量,是可以重复声明的,这有个好处就是写起来比较灵活,不会抛出重复声明的异常。


四、let 变量声明

let 是块级作用域的本地变量。与 var 声明不同的是,let不允许重复声明同一个变量,将会抛出 SyntaxError 异常,但可以修改变量的值。

// 块级作用域

    let a = 1;
    console.log(a)          // 打印:1
    a = 2;
    // let a = 3;              // 抛出 SyntaxError

console.log(a)              // 抛出异常 ReferenceError

let 声明的变量不存在变量提升,在变量初始化前访问该变量会抛出 ReferenceError 异常,自块开始到在初始化之前属于暂存死区。

// 不存在变量提升
console.log(a)         // 抛出 ReferenceError
let a = 1;


    console.log(b)     // 抛出 ReferenceError
    let b = 2;

使用 let 声明的变量能够解决 三、var 变量声明 ⇨ 5、意想不到的全局污染 中所提到的全局污染。

  • 此时程序能正确输出我们所期望的值,1-10之间的数。

     for (let i = 1; i <= 10; i++) 
         // 延时一秒后执行
         setTimeout(function () 
             console.log(i);		// 输出1-10
         , 1000)
     
    
  • 此时每个变量在各自的作用域里各司其职,河水不犯井水,对于我们编写代码来说不会出现一些意外的值。

    let x = 1;
    
    function func1() 
        let y = 2;
    
        function func2() 
            let x = 4;
            let y = 5
            let z = 6;
            console.log(x, y, z)    // 打印:4, 5, 6
        
    
        func2()
        console.log(x, y)	        // 打印:1 2
    
    
    func1()
    console.log(x)				    // 打印:1
    

五、const 常量声明

const 是块级作用域的本地常量。与变量不同的是,常量不支持重复声明也不支持修改,若是存在修改行为则会抛出 TypeError 异常。

// 块级作用域

    const BASE = "块级";
    console.log(BASE)        // 正常打印
    // const BASE = "重复赋值"   // 抛出 SyntaxError
    // BASE = "修改";           // 抛出异常 TypeError

console.log(BASE)           // 抛出异常 ReferenceError

常量名和其他声明方式一样,都可以大小写字母,但程序员之间会使用全大写进行命名,这是为了便于辨别常量类型,可以说是程序员之间的一种默契。

// 声明常量
const BASE = "常量名大写"
// 声明并初始化两个个变量
const BASE_NAME1 = 1, BASE_NAME2 = 2;

const 常量不存在变量提升,在常量初始化前访问该常量会抛出 ReferenceError 异常,自块开始到在初始化之前属于暂存死区。

// 不存在变量提升
console.log(a)         // 抛出 ReferenceError
const a = 1;


    console.log(b)     // 抛出 ReferenceError
    const b = 2;

对于性能来说,const 不允许重新赋值的,所以转换逻辑很简单,其潜在优化比较好。但是这种差异是细微的,几乎察觉不到,使用常量更多是注重代码风格,便于阅读。


六、var、let和const应用场景

声明描述作用域是否存在变量提升
var声明一个变量,可同时将其初始化为一个值全局作用域
let声明一个块级本地变量,可同时将其初始化为一个值[块级/局部]作用域
const声明一个只读的命名常量[块级/局部]作用域
  • 如果一个变量在不会发生改变,在大多数情况下应使用 const 进行声明将其变为常量。这样有利于代码的阅读,不用考虑这个变量会不会发生改变,还能提高程序的 潜在 执行效率。
  • 大部分情况下都不应该使用 var 进行声明,因其全局破坏的影响,尽量使用 letconst 进行取缔。
  • 在使用 WebStorm 编辑器进行代码书写时,使用 var 进行声明会有明确的弱警告提示。

参考资料


推荐文章🍗

😝给笔者加个🍗

以上是关于varletconst声明方式的区别的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 各声明varletconst方式区别『详解』

varletconst区别

varletconst的区别

varletconst的区别

varletconst的区别

varletconst的区别