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 }) 
posted @ 2018-07-18 01:02  Skd一路花开  阅读(2000)  评论(0编辑  收藏  举报