• ES6中的变量声明


    一、为什么要是用let和const代替var声明变量

      1、var声明的变量是函数作用域的,存在变量的提升。(变量的声明会被提前到当前作用域的最前面)

     1 //变量提升
     2 function f(condition){
     3     if(condition){
     4         var value="blue";
     5         return value;
     6     }       
     7     else{
     8         console.log(value); //undefined
     9     }
    10     console.log(value);  //undefined
    11 }
    12 f(false);

        由于var声明的变量存在变量提升,所以当condition为false时,输出变量不会提示value变量未定义的错误,上面的代码类似于

     1 //变量提升
     2 function f(condition){
     3     var value;
     4     if(condition){
     5         value="blue";
     6         return value;
     7     }       
     8     else{
     9         console.log(value); //undefined
    10     }
    11     console.log(value);  //undefined
    12 }
    13 f(false);

      2、var可以在同一作用域内声明一个变量多次。变量的值为最后一次声明的 

    1 var value=10;
    2 var value="100";
    3 console.log(value)//100

       3、全局作用域的绑定

      使用var声明的全局变量会自动绑定为全局对象的属性。从而又可能覆盖已经存在的全局属性。

    1 console.log(global.RegExp);//[Function: RegExp]
    2 var RegExp="aaa";
    3 console.log(global.RegExp);//"aaa"

      代码不要写在js文件中使用node 文件名去测试,因为node会把一个文件作为一个模块,声明的变量不是全局对象的属性。

      可以node的repl中测试或者浏览器环境中。

      使用let和const声明的变量不会覆盖全局对象的属性,而是遮盖他  

    1 let RegExp="aaa";
    2 console.log(global.RegExp===RegExp);//false  

    二、let和const

      通过let和const声明的变量是块级作用域,只在{}生效;类C语言多采用块级作用域,这样做更符合我们的习惯。

      let声明

      a、let声明的变量是块级作用域,且不存在变量提升机制,所以使用let声明的 变量只有放到当前作用域的最前面,才能在整个作用域中使用。

     1 function f(condition){
     2     if(condition){
     3         let value="blue";
     4         return value;
     5     }       
     6     else{
     7         //console.log(value); //ReferenceError: value is not defined
     8     }
     9     console.log(value);  //ReferenceError: value is not defined
    10 }
    11 f(true);

      变量离开if块就会被销毁,其他的块作用由于没有什么变量vaue,所以直接使用会抛出异常。

      b、let声明的变量在同一作用域中禁止重复声明

    1 //var value=10;
    2 let value=10;
    3 let value="100";//SyntaxError: Identifier 'value' has already been declared
    4 console.log(value)//100

     当在不同的作用域声明变量的时候,不会报错。

    1 //var value=10;
    2 let value=10;
    3 function f(){
    4     let value="1dad";
    5     console.log(value)//'1dad'
    6 }
    7 console.log(value)//10
    8 f()

      const声明

      a.const关键字用来声明一个常量,声明后变量的值不可以更改。const声明变量必须初始化。

    1 const a='dada'
    2 const b;//SyntaxError: Missing initializer in const declaration

      b、const声明已存在的变量会报错,(无论是let和const) 

    var a=10;
    //let a=10
    const a='dada'//Identifier 'a' has already been declared

      c、用const声明对象

      const声明的变量不允许修改变量的值。由于变量存在的是对象的值得引用,所以const声明的对象可以修改对象的属性,但是不能把修改对象的引用。

    const  a={name:'yiluhuakai'};
    a.name="aaa";
    console.log(a.name)//'aaa'
    a={};//TypeError: Assignment to constant variable.

    三、临时死区

      使用let和const声明的变量不会进行变量提升,变量的作用域的开始到变量声明之前的位置成为临时死区,当在该区域使用变量时回抛出异常,即使是使用相对安全的typeof操作符。  

    typeof a;//作用域外不会抛出异常
    function f(){
       // typeof a;//ReferenceError: a is not defined
        if(true)
        {
            ;
        }
        let a=10;
    }
    f();

    四、循环中的函数

      在循环中定义一个函数,打印当前的循环的变量i;

     1 var arr=[];
     2 for(var i=0;i<10;i++){
     3     arr.push(function(){
     4         console.log(i);
     5     })
     6 }
     7 //打印
     8 arr.forEach(function(item){
     9     item();//输出10次10
    10 })

       为什么输出结果是10次10呢,因为上面var声明的便利会提升到循环外面,循环中函数共享(闭包)同一个i。

       立即调用调用函数可以解决这个问题。  

     1 var arr = [];
     2 for (var i = 0; i < 10; i++) {
     3     arr.push((function (value) {
     4         return function () {
     5             console.log(value)
     6         }
     7     })(i))
     8 }
     9 //打印
    10 arr.forEach(function (item) {
    11     item();//0 1 2 ... 8 9
    12 })

      将i作为行参传给函数,value会复制i的值,这个之就是内部函数打印的值。

      更简单的解决办法:使用let使命变量

     1 var arr=[];
     2 for(let i=0;i<10;i++){
     3     arr.push(function(){
     4         console.log(i);
     5     })
     6 }
     7 //打印
     8 arr.forEach(function(item){
     9     item();//输出0 1 ... 8 9
    10 })

      使用let声明的变量每次循环都会声明一个新的变量,所以之前迭代的同名变量初始化j将其初始化,所以每次输出的值都不一样。

       for-in和for-of也是一样。

     1 var arr=[];
     2 var object={
     3     a:true,
     4     b:1,
     5     c:2
     6 }
     7 for(let key in object){
     8     arr.push(function(){
     9         console.log(key)
    10     })
    11 }
    12 arr.forEach(function(item){
    13     item() //a b c
    14 })

      使用let会每次声明一个新的变量保存key,所以会每次输出不同的值。使用var使用的是同一个变量,最终输出都是c.

      const用在循环中 

     1 var arr=[];
     2 for(const i=0;i<10;i++){
     3     arr.push(function(){
     4         console.log(i);
     5     })
     6 }
     7 //打印
     8 arr.forEach(function(item){
     9     item();//TypeError: Assignment to constant variable.
    10 })

      在普通的for循环中使用const声明变量时,第一次循环const i=0不会报错,但是当第二次循环中初始化i后,对i执行i++操作时会报错。所以不能在普通的循环中使用const声明循环变量。

      但是在for-of和for-in循环中使用const不会出现问题,因为只会对新创建的变量初始化,不会去改变变量的值。

     1 var arr=[];
     2 var object={
     3     a:true,
     4     b:1,
     5     c:2
     6 }
     7 for(const key in object){
     8     arr.push(function(){
     9         console.log(key)
    10     })
    11 }
    12 arr.forEach(function(item){
    13     item() //a b c
    14 }) 
  • 相关阅读:
    记录一次线上优化流程
    php ignite 使用问题记录
    invalid contrller specified 错误分析及解决
    koa 2 的 async 和 await 语法
    koa 2 的安装
    vue 自定义组件 v-model双向绑定、 父子组件同步通信的多种写法
    VS2019专业版和企业版激活密钥
    RE:ゼロから始める PKU 生活 episode 2
    CSP-S 2020 游记
    ioi2021集训队作业
  • 原文地址:https://www.cnblogs.com/yiluhuakai/p/9326953.html
Copyright © 2020-2023  润新知