函数的优点、预解析、作用域

321 阅读4分钟

函数的优点

  1. 封装 (把函数保存起来) 2.复用 3.延迟执行 ;
//第一版本
var a = 10;
var b = 20;
var c = 30;
console.log(a+b+c);  // 一旦通过浏览器打开  代码就立刻执行
//第二版本  函数优化版本
function add() {
     var total = 0;
     for (var i = 0; i < arguments.length; i++) {
            total += arguments[i];
   }
            //console.log(total)
            return total;
 }
  // 不想让add 里的代码 在打开浏览器的时候立刻执行
  // 通过事件来延迟执行 函数里的代码 ;
        var a = 10;
        var b = 20;
        var c = 30;
        var res = add(a, b, c);
        console.log(res);//执行60

函数的预解析

预解析 :js内部在执行js之前会把js解释一遍 然后再执行 ;

1.变量预解析 (变量提升);

1.1变量

    console.log(a); // 单独打印会报错 
 console.log(a); // 报错? 不会报错 结果是undefined
 var a = 10;  
 
 解析上面的代码执行等于变量提升,声明前置了,变量一旦被声明 那么这个变量的声明在js解释阶段会提升到最前面。
 var a;//把a的声明提升到最前面 
 console.log(a); 
 a = 10; //// a的赋值没有被提升 声明前置

总结 : 变量声明时候,会把变量声明提升到代码最前面;打印变量会得到undefined ; 声明前置是系统内置的,会自动去重排代码顺序 ;

2.函数的预解析 (声明前置);

函数定义有两种 声名式 赋值式

console.log(fn);//fn 函数
function fn(){     // 会提升
   console.log("fn");
}
 console.log(fn);  // fn 函数
 var fn = "123";  //  会提升 同时这边fn函数有赋值
 console.log(fn);  // 123;

在js里 函数被称为最高级 函数优先级更高

函数内部的提升

1.函数内部的变量提升

 function fn(){
            console.log(a);
            var a = 10;
 }
fn();//undefined  变量提升了 变量值没有提前。
  1. 函数内部的函数声明提升;
 function fn(){
      console.log("fn");
      test();
      function test(){
      console.log("test");
 }
}
 fn();//执行 fn
             test

3.函数和变量同时提升

//预解析前
function fn(){
     console.log(a);
     var a = 20;
     console.log(a);
     function a(){    //会提升到最前
         console.log("a函数");
   }
         console.log(a);
}
fn();
//预解析后
function fn(){
   function a(){    //会提升到最前
         console.log("a函数");
   }
     console.log(a);//执行a函数
     var a = 20;
     console.log(a);//执行20
     console.log(a);//执行20
}
fn();//执行结果ƒ a(){
               console.log("a函数");
           }
               10
               10

4.函数参数和变量提升

// 变量的提升 不会影响 传入的参数的值;赋值后会修改变量 
        function fn(a){
            console.log(a);
            var a = 10;
            console.log(a);
        }
        fn(2);//结果 2
                    10

5.函数的提升:会影响到参数的传入的值;

//预解析前
function fn(a){
            console.log(a); // a 的打印结果是??
            function a(){    
                console.log("a函数");
            }
        }
        fn(2);//ƒ a(){    
                console.log("a函数");
            }
//预解析后
function fn(a){
    function a(){    
       console.log("a函数");
     }
       console.log(a); // a 的打印结果是?    
}
        fn(2);//打印结果是:ƒ a(){    
                console.log("a函数");
                           }
  1. 变量提升的一个bug 大坑 记住!!!
console.log(a);  // a 是啥? 1. undefined 2.报错  
// 结果是 undefined  有点不符合逻辑
        if(false){
            var a = 10;
        }
console.log(a);//单独的这个是报错

函数内部的提升 :1.变量;2.参数; 3. 函数;

提升预解析中的提升,函数的优先级始终比变量和参数的优先级更高

注意声名式函数式函数提前,赋值式函数是属于变量提前。

function fn(){
       console.log(a) ; // undefined
       var a = 10;
       console.log(a);  //  10
   // 注意赋值式函数是一个变量的提升
       var a = function(){
       console.log("a")
    }
       console.log(a);  //函数
}
fn();//执行结果 undefined
            10
            ƒ (){
                console.log("a")
            }
        function fn(){
            console.log(a) ; // 函数
            var a = 10;
            console.log(a);  //  10
            function a(){   //声名式函数提前了
               console.log("a");
         }
               console.log(a);  //10
        }
        fn();//执行结果  ƒ a(){
                          console.log("a");
                   }
                         10
                         10

函数的作用域

作用域: 一个变量或者是一个函数的使用范围 ;

1.全局作用域 (js里全局内置的变量是window)

console.log(window); //系统内置的全局对象 注意不是windows, windows是系统

var a=10; console.log(window.a)//一般情况下 都会省略window全局变量

// 全局作用域 :就是在全局范围内都可以访问的区域;

 function fn(){
        console.log("fn");
 }
        console.log(fn);
      //console.log(window.fn);
  1. 局部作用域(函数作用域)(一个函数包裹的区域);
function fn1(){
      var a = 10;
}
fn1();
function fn2(){
      console.log(a);//这里的a也是在fn1函数外面 不在fn1函数内,不起作用
}
fn2();//报错

总结:局部作用域,变量只在函数大括号包裹的内部才有作用。

局部作用域的访问规则

1.局部可以访问到全局的内容

var a = 10;
function fn(){
console.log(a);
}
fn();//执行结果 10 自己没有找上层全局作用域

  1. 如果函数有嵌套关系 变量访问会逐层向上查找,如果当前作用域有改变量会先用当前作用域的
var a = 10;//自己当前作用域有改变量就执行不到全局
function fn(){
      var a = 20;//自己有变量值就用优先用自己的
      console.log(a);
   }
  fn();//执行结果  20
var a = 10;
console.log(a);
//全局作用域
function fn1(){
      // fn1 的作用域
     var a = 20;
     function fn2(){
      // fn2的作用域
           var a = 30;
           console.log(a);
}
            fn2();
 }
fn1();//执行结果 10 
                30

总结:嵌套作用域访问规则

  1. 变量就近原则
  2. 逐层向上查找(作用域是由小的到大的作用域查找) ,都找不到就会报错。
  3. 注意:访问一定不能向下查找。