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。

  • 相关阅读:
    DVI与DVI-D的区别
    easyui.combotree.search.js
    显示实时日期时间(html+js)
    Jquery 内容简介
    EasyUI 格式化DataGrid列
    EasyUI DataGrid 添加排序
    EasyUI DataGrid 复选框
    EasyUI 自定义DataGrid分页
    EasyUI DataGrid能编辑
    EasyUI 我的第一个窗口
  • 原文地址:https://www.cnblogs.com/zingp/p/6100666.html
Copyright © 2011-2022 走看看