zoukankan      html  css  js  c++  java
  • JS

    函数作用域

     函数作用域的含义是指,属于这个函数的全部变量都可以在整个函数范围内使用及复用(事实上在嵌套作用域中也可以使用)。

      函数和函数表达式分辩

      看function出现的位置,如果是声明的第一个词就是函数,否则为函数表达式

      (function foo() {...})  函数表达式,只能在{...}位置被访问,外部作用域则不行

      function() {...}  函数声明

    1. var 隐式定义变量
    function foo() {
      var a = b = 1  
    }
    
    foo()
    
    console.log(a)  // undefined
    console.log(b)   // 1

    var a = b = 1 隐式创建了一个全局变量b,a的作用域在foo函数内,因此外部不能访问函数内部变量,可以访问全局变量。如果需要同时创建两个函数内变量,可以使用 var a = 1 , b = 1

     

    块作用域

    js中没有块级作用域,使用var声明的变量时写在哪里都是一样的,因为他们最终都会属于外部作用域

    for(var i = 0; i < 10; i++) {
      console.log(i)  
    }
    
    等价于
    
    var i = 0;
    for(; i < 10; i++) {
      console.log(i)      
    } 

    附:经典面试题

    for(var i=0; i<=5; i++) {
       setTimeout(function timer() {
            console.log(i)
        }, 1000)         
    }
    
    // 输出为 6 6 6 6 6 6
    
    // 闭包解决作用域问题,每次存储i的值
    for(var i=0; i<=5; i++) {
        (function(j){
            setTimeout(function timer() {
                console.log(j)
            }, j*1000)
        })(i)    
    }    
    
    // 输出为 1 2 3 4 5 6  
    // es6中添加了let用来劫持块作用域,简单的解决上面的问题

    首先js是单线程,先执行同步操作,后执行异步操作,setTimeout为异步,所以先执行完for循环后执行定时器,但由于i为全局变量,for循环执行完后i被改变为6,此时有6个定时器被阻塞分别执行,即输出为6个6

    使用闭包每次循环将i值存储起来,互不影响,即达到顺序输出的结果

    变量提升

    consoel.log(a)
    var a = 2
    
    变量提升转换为
    
    var a
    console.log(a)   // undefined
    a = 2
    
    // ------------------------------------
    a = 2
    var a
    console.log(a)
    
    变量提升转换为
    
    var a
    a = 2
    console.log(a) // 2

    函数提升

    foo()
    function foo() {
        a = 2
        console.log(a)   // 2
        var a  // 提升变量到第一行
    }   // 提升函数声明到调用之前,因此不会报错
    
    // -------------------------------------------------
    foo()   // TypeError   函数表达式不会被提升
    
    var foo = function bar() {} 

    * 函数提升会优先于变量提升,变量与方法同名会被忽略,后面的方法会覆盖前面的方法

    foo()
    function foo() {
        console.log(1)
    }          // 被提升至调用之前
    var foo  // 提升至方法之后,方法提升优先于变量
    function foo() {
        console.log(2)
    }          // 紧跟上一个方法提升
    
    等价于
    function foo() {
        console.log(1)
    }  
    function foo() {
        console.log(2)
    } 
    var foo
    foo()   // 输出2,第二个方法将第一个覆盖,变量未赋值,忽略

    try...catch...finally语句

    try执行代码块,catch捕获异常,finally不管是否抛出异常都必须执行的语句

    语句的三种组合形式:

      1. try{...} catch(e) {...}

      2. try{...} finally{...}

      3. try{...} catch(e) {...} finally{...}

    执行顺序:如果内部抛出异常,外部捕获之前必须要先执行内部的finally

    try {
      try {
            throw new Error('oops')
        } catch(e) {
            console.log('inner', e)
            throw(e)
        } finally {
            console.log('inner finally')
        }
    } catch(e) {
        console.log('outer', e)
    }
    
    // inner oops
    // inner finally
    // outer oops
  • 相关阅读:
    近似与精确——《狂人C》习题解答15(第三章习题5)
    策略、次序和测试—《狂人C》习题解答16(第三章习题6)
    华丽的递归——将正整数表示为平方数之和
    Horner's rule——《狂人C》习题解答5(第二章习题8)
    .NET牛人需要了解的问题[转]
    Ajax的一个封装[原创]
    公司项目改进之权限篇[原创]
    【方案解决】ncelab: *E,CUIOCP Outofmodule reference terminating in a VHDL scope is not allowed
    【原创】关于setup和hold的深入浅出【Verilog】
    LEC3南京大学操作系统重点简答题素材中断处理
  • 原文地址:https://www.cnblogs.com/zhoujin-Jojo/p/13714669.html
Copyright © 2011-2022 走看看