zoukankan      html  css  js  c++  java
  • 四句话总结JavaScript作用域

    上一篇文章中简单介绍了一下JS作用域,本篇将作进一步探究和总结。

    前言:JavaScript的作用域一直以来都是前端开发中比较难以理解的知识点,JavaScript6中新引入了 let 关键字,用于指定变量属于块级作用域,本次先忽略这个点。

    第一句话:JavaScript以函数作为作用域(忽略let)

      很多语言如c#,java都是以代码块作为作用域即大括号也是一个作用域,JavaScript却是以函数作为作用域,如果你对python比较了解,理解起来应该很easy。

    在c#中下面的代码将直接报错:

     1 public void Func(){
     2     if(1==1){
     3         string name = 'Java';
     4                             
     5     }
     6     console.writeline(name);
     7                         
     8 }
     9 Func()
    10  // 报错    

    在JavaScript语言中无块级作用域:

    1 function Main(){
    2     if(1==1){
    3         var name = 'seven';
    4     }
    5     console.log(name);
    6 }
    7 // 输出: seven

    我们先来回忆一下python的作用域(如果不会python可以跳过,不影响后面阅读):

     1 # 情况一:
     2 def func():
     3     if 1 == 1:
     4         name = 'alex'
     5     print(name)
     6 func()
     7 # 成功
     8 
     9 # 情况二:
    10 def func():
    11     if 1 == 1:
    12         name = 'alex'
    13     print(name)
    14     
    15 func()
    16 print(name)
    17 # // 报错

    再来看看JavaScript采用函数作用域:

    1 function Main(){
    2     var innerValue = 'seven';
    3 }
    4  
    5 Main();
    6  
    7 console.log(innerValue);
    8  
    9 // 报错:Uncaught ReferenceError: innerValue is not defined

      在JavaScript中每个函数作为一个作用域,在外部无法访问内部作用域中的变量。console.log(innerValue)访问函数Main()中的变量肯定是不行的。

    第二句话:JavaScript函数的作用域在函数未被调用之前,已经创建

      在JavaScript中如果不创建(声明)变量,直接去使用,则报错:

    1 console.log(x);
    2 VM199:1 Uncaught ReferenceError: x is not defined(…)

      JavaScript中如果创建值而不赋值,则该值为 undefined,如:

    1 var num;
    2 console.log(num);
    3 
    4 //undefined

         了解了这个看看下面这个函数:

    1 function func(){
    2     if(1==1){
    3         var name = 'alex';
    4     }
    5     console.log(name);
    6 }

      在浏览器中直接输入这个函数会得到undefined,而不是报错,就说明变量name在函数调用之前就创建(声明)了,但没有被赋值。

    第三句话:函数的作用域存在作用域链,并且也是在被调用之前创建

     1  1 <script>
     2  2     x = "alex";
     3  3     function func() {
     4  4         var x = "eric";
     5  5         function inner() {
     6  6             var x = "tony";
     7  7             console.log(x);
     8  8         }
     9  9         inner();
    10 10     }
    11 11     func();
    12 12 </script>

    输出结果是tony。

    如上述代码则出现三个作用域组成的作用域链,如果出现作用域链后,那么寻找变量时候就会出现顺序,对于上述实例:

    当执行console.log(xo)时,其寻找顺序为根据作用域链从内到外的优先级寻找,如果内层没有就逐步向上找,直到没找到抛出异常。

     

     练习题1:

     1 x = "alex";
     2 function func() {
     3     var x = "eric";
     4     function inner() {
     5         console.log(x);
     6     }
     7     return inner;
     8 }
     9 var res = func();
    10 res();

    结果:eric

    上述代码,在函数被调用之前作用域链已经存在:

    • 全局作用域 -> func函数作用域 -> inner函数作用域

    当执行【ret();】时,由于其代指的是inner函数,此函数的作用域链在执行之前已经被定义为:全局作用域 -> Func函数作用域 -> inner函数作用域,所以,在执行【ret();】时,会根据已经存在的作用域链去寻找变量。

    练习题2:

     1 x = "alex";
     2 function func() {
     3     var x = "eric";
     4     function inner() {
     5         console.log(x);
     6     }
     7     var x = 'tony';
     8     return inner;
     9 }
    10 var res = func();
    11 res();

    结果:tony

    第四句话: 函数内局部变量 声明提前

    1 function func(){
    2     console.log(xo);
    3     var xo = 'alex';
    4 } 
    5       
    6 func();
    7 // undefined

    上述代码,不报错而是输出 undefined,其原因是:JavaScript的函数在被执行之前,会将其中的变量全部声明,而不赋值。所以,相当于上述实例中,函数在“预编译”时,已经执行了var xo;所以上述代码中输出的是undefined。

  • 相关阅读:
    ECharts之柱状图 饼状图 折线图
    Vue自定义指令(directive)
    HDU 1231 最大连续子序列
    POJ 2533 Longest Ordered Subsequence
    HDU 1163 Eddy's digital Roots
    HDU 2317 Nasty Hacks
    HDU 2571 命运
    HDU 4224 Enumeration?
    HDU 1257 最少拦截系统
    HDU 2740 Root of the Problem
  • 原文地址:https://www.cnblogs.com/zingp/p/6100666.html
Copyright © 2011-2022 走看看