最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • [前端ABC]彻底弄懂ECMAScript的变量声明var, let和const

    正文概述 掘金(用户4947375079080)   2021-03-19   563

    前端ABC系列旨在快速讲解前端重要的知识点,并给出最佳实践。

    Github传送门,欢迎star。

    1 ECMAScript的变量声明

    ECMAScript中有三个关键字可以用来声明变量,分别是var, let, const。三者的通用格式如下:
    [关键字] [标识符] = [值]
    const message = 'hello'
    其中= [值]是对于var和let是可选的,对于const则是必须的。如果不选的话,变量将会被赋予默认值undefined
    接下来让我们逐步搞清三种变量声明方式的区别。

    2 var

    使用var关键字进行变量声明是ECMAScript 2015之前的唯一变量声明方式。根据var声明语句所在作用域的区别,声明的变量具有不同的行为:

    2.1 在函数作用域中

    此时声明的变量会成为包含它的函数的局部变量,函数执行完毕后立即销毁(在没有闭包的情况下),如下所示:

    function demo(){
        var message = 'hello'
    }
    
    demo()
    
    //ReferenceError: message is not defined
    console.log(message)
    

    2.2 在全局作用域或其他块作用域中

    此时声明的变量将变成全局变量,并成为window对象的属性(浏览器环境)。如下所示:

    var message = 'hello'
    
    function demo(){
        console.log(message)
    }
    
    demo() //hello
    
    
    if(true){
        var message = 'hello'
    }
    
    function demo(){
        console.log(message)
    }
    
    demo() //hello
    
    window.alert(window.message) //hello
    

    2.3 特殊情况:省略var关键字

    值得注意的是,使用var声明变量可以省略var关键字,这样声明得到的变量将变成全局变量,并成为全局对象的属性。如下所示:

    function demo(){
        message = 'hello'
    }
    
    demo()
    
    console.log(message) //hello
    
    console.log(globalThis.message) //hello
    

    其中globalThis是标准化的全局对象。 通常而言,这会导致意外的全局变量,是不好的实践。

    使用var进行变量声明有以下几个特点:

    • 进行重复声明不会报错
    var message = 'hello'
    var message = 'world'
    console.log(message) //world
    
    • 存在变量提升
    //可以在变量声明前访问到该变量
    console.log(message) //undefined
    var message = 'hello'
    

    ECMAScript在运行时会把var变量声明拉到作用域的顶部,因此上面的代码等价于

    var message //undefined
    console.log(message) //undefined
    message = 'hello'
    

    3 let

    letconst是ECMAScript 2015出现的新的变量命名关键字。它们命名变量的行为和var差别巨大。

    • let声明所在的范围会成为块作用域,意味着块之外无法引用该变量
    if(true){
        let message = 'hello'
    }
    
    //ReferenceError: message is not defined
    console.log(message)
    

    如之前所说,在函数作用域中使用var声明的变量是局部变量,函数作用域外也无法访问。不过在if, while等语句块中使用var声明的变量,语句块之外是可以访问的,因为使用var声明变量不存在块作用域概念。如下所示:

    function demo(){
        var message = 'hello'
    }
    
    //ReferenceError: message is not defined
    console.log(message)
    
    if(true){
        var message = 'hello'
    }
    
    console.log(message) //hello
    

    • 进行重复声明会报错
    let message = 'hello'
    
    //SyntaxError: Identifier 'message' has already been declared
    let message = 'world'
    

    • 全局作用域中let声明的变量不会成为全局对象的属性
    let message = 'hello'
    console.log(globalThis.message) //undefined
    

    • 存在暂时性死区

    **let**声明的变量不会在作用域中得到提升。因此在**let**声明之前对该变量进行引用都会抛出**ReferenceError**,我们把**let**声明之前的这个阶段称作该变量的“暂时性死区”(temporal dead zone)。如下所示:
    //ReferenceError: Cannot access 'message' before initialization
    console.log(message)
    let message = 'hello'
    

    事实上,JavaScript引擎已经注意到了之后声明的变量,不过该变量是uninitialized的状态,引擎不允许对该变量的任何引用直到该变量被声明。

    4 const

    const声明变量的行为与let基本相同,不过仍有两点需要注意:

    • 如前所说,使用const声明变量时必须同时以显式的值对变量进行初始化,否则会报错:
    //SyntaxError: Missing initializer in const declaration
    const message
    
    • const声明通常表示声明的变量是一个常量,因此修改它的值(原始类型的值和引用类型的引用)会报错
    const message = 'hello'
    //TypeError: Assignment to constant variable.
    message = 'world'
    
    const message = {a:'hello'}
    //TypeError: Assignment to constant variable.
    message = {b:'hello'}
    

    需要注意的是,如果变量指向的是引用类型,该限制只适用于变量指向的引用类型的引用。修改这个引用类型的内部属性并不会报错。如下所示:

    const message = {a:'hello'}
    message.b = 'world'
    //{ a: 'hello', b: 'world' }
    console.log(message)
    

    5 最佳实践

    • 不使用var

    var声明变量的行为怪异,会造成各种问题,因此使用letconst是更好的选择。

    • 优先使用const

    使用const可以帮助引擎发现意外赋值导致的非预期行为。因此,只有在我们知道变量的值在未来可能会改变时才使用let,除此之外使用const是更好的选择。

    6 思考

    以下代码会输出什么?你知道原因吗?

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

    起源地下载网 » [前端ABC]彻底弄懂ECMAScript的变量声明var, let和const

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元