JavaScript作用域

本篇文章的重点是学习如何使用 JavaScript 新的语法 let 声明变量以及作用域的理解。

1、let 基本介绍

    JavaScript ES6 引入了 let ,用 let 声明变量,解决了 JavaScript 没有块级作用域的问题(注意:ES3 的 catch 分句会产生块作用域)

    对于新手而言,ES6 之前,JavaScript 没有块级作用域,使用 var 声明变量,会让 JavaScript 不易懂和难以调试,用不好甚至有内存泄露的可能。至于为什么会这样,主要是没有清楚作用域的概念,下面首先了解一下什么是作用域。

2、作用域介绍

    1)作用域

        作用域简单的来说,就是一套寻找变量的规则,用于确定在何处以及如何查找变量。 在 ES6 代码之前,只有全局作用域和函数作用域。

    当一个块或函数嵌套在另一个函数时,就发生了作用域嵌套,如下所示,就有三个嵌套作用域:

   function foo(a) {

            var b = a * 2;

            function bar(c) {

                    console.log (a, b, c) ;

            }

            bar (b * 3);

    }

    foo ( 2 ) ; // 2, 4 , 12

// 1、全局作用域,其中有一个标识符:foo;

// 2、  foo 创建的函数作用域,其中有三个标识符:a ,bar 和 b

// 3、bar 创建的函数作用域,其中有一个标识符:c 

   如何在嵌套作用域中寻找变量?

    引擎从当前作用域开始查找变量,如果找不到,就会向上一级继续查找。当抵达最外层全局作用域时,无论找到还是没有找到,查找过程中都会停止。

2)全局作用域和函数作用域

    使用 var 声明变量时,如果在函数外声明,就是全局变量,任何函数都可以进行使用,这就是全局作用域查找。

    如果在函数内使用 var 声明变量,就是函数作用域查找,只能在函数内部进行访问,外部不能进行访问:

    var a = 12; //全局作用域都能进行访问

    function myFunction () {

        alert ( a );  // 12

        var b = 13 ;     

        if ( true ) {

            var c = 14 ; // 函数内部可以访问

        alert ( b ) ; //13

        }

        alert ( c ) ;  //14

    }

    myFunction ();

    alert ( b ) ;  //undefined

    3)块级作用域

在 ES6 中引入了 let ,避免了有 var 声明变量的一些问题,让变量和函数不仅可以属于所处的作用域,也可以属于某个代码块 (通常是 { ... } 内部) , 另外,在块级作用域定义的变量,块级作用域外是无法访问的。

 let a = 12 ; //全局作用域 , 可以访问

  function myFunction () {

        console.log ( a ) ; // 12

        let b = 13;

        if ( true ) {

            let c = 14;

            alert ( b );  //13

        }

        alert ( c ) ; //undefined {}外,因此无法访问

    }

myFunction ();

alert( b ) ; // undefined { } 外,因此无法访问


3、var 和 let 的区别

1) let 和 const 不存在变量提升机制

    创建变量的六种方式中:var / function 有变量提升, 而 let / const / class / import 都不存在这个机制

2)var 允许重复声明,而 let 不允许重复声明

    在相同的作用域 ( 或执行上下文中)

    —— 如果使用 var / function 关键字声明变量并且重复声明, 是不会有影响的 (声明第一次之后,之后再遇到就不会再重复声明了)

    —— 但使用 let / const 就不行, 浏览器会校验当前作用域中是否已经存在这个变量了,如果存在了,则再次基于 let 等重新声明就会报错

3)let 会产生块级作用域

4、重复定义变量的问题

用 var在同一个作用域重复定义变量,后者将会覆盖前者声明的变量的值,如下:

var a = 0 ; 

var a = 1 ;

alert ( a ) ; // 1

function myFunction ( ) {

        var b = 2; 

        var b = 3;

        alert ( b ); // 3;

    }

    myFunction ( );

使用 let 在同一作用域下重复定义变量,将会产生 Syntaxerror 的错误,如下:

let a = 0;

let a = 1; // SyntaxError

function myFunction ( ) {

        let b = 2;

        let b = 3 ; // SyntaxError

        if ( true ) {

            let c = 4; 

            let c = 5 ; // SyntaxError

            }

    }

myFunction();

如果你在嵌套作用域里进行重新定义变量 , 虽然变量名相同 , 但是不是同一变量,如下:

var a = 1;

var b = 2; 

function myFunction ( ) {

        var a = 3; // different variable

        let b  = 4 ; //different variable

        if ( true ) {

            var a = 5 ; // overwritten

            let b = 6 ; //different variable

            console.log (a ); //5

            console.log ( b ); //6

        }

        console.log ( a ) ; //5 

        console.log ( b ) ; // 4

    }

    myFunction ( );

console.log ( a );

console.log( b );

5、提升概念的问题

直觉上会认为编译器会由上到下一行行的执行,起始并不正确,函数声明和变量声明都会被提升 ( 使用 var 声明变量 , let 声明变量将不会被提升 )。函数首先会被提升 , 然后才是变量提升。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容