JavaScript之function(下)简介

1.作用域的概念

任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。
局部作用域和全局作用域
在JavaScript中,变量的作用域有全局作用域和局部作用域两种。
引入:

<body>
    <script>
        //1.变量,函数作用的范围???
        //2.变量为什么前置访问undefined,而函数可以任何地方调用????
    </script>
    <script>
        alert(a) //报错Uncaught ReferenceError: a is not defined(为什么???)
    </script>
    <script>
        alert(a) //undefined
        var a = 3;
        alert(a); //3
    </script>
    <script>
        alert(a) //3
    </script>
</body>

全局作用域(变量):整个程序都有效,即整个代码中都可以调用(特殊:变量前面没有添加var变成全局的属性,也是整个程序都有效)。
(1)全局作用域(全局变量):对整个script块内都是有效,也可以理解成作用于整个文档。(一般情况下一个文档只有一个script块,要是有多个script,那么全局变量会对所在的script块以及后面的script块起作用,在之前的script块输出变量会报错)(全局变量可以进入函数内)

   var a=5;
    function fn(){
 return a;//a是全局变量,此处的a就是5,return把5返回给调用者,谁调用给谁
      }
  alert(fn());//5调用函数,并在alert显示

(2)特殊情况,如果声明的变量前面没有var关键字,变量变成了全局的属性(全局变量)

 function fn(){
            a=1;//全局属性,变量是window下面的属性。
             return a;
         }
         fn();(函数必须调用否则,函数体等于不存在)
         console.log(a);//1,a是全局属性,故函数外也可以获取a的值

变量是window下面的属性
上述的a就是window下面的属性,只不过正规写法是window.a,window被省略了。

   var num=100;
     console.log(num);//100
     console.log(window.num);//100
     window.document.write('abc');

局部作用域(变量):只对函数内部有效,即只能在本变量声明的函数内部调用,函数外部无法获取。

function fn() {
            var num = 5;
            return num;
        }
        alert(num)//报错,原因是num定义在函数体内,无法获取,
        //Uncaught ReferenceError: num is not defined


function a() {
            //alert(num); //报错:Uncaught ReferenceError: num is not defined
            function b() {
                var num = 4;
                alert(num)//输出4
            } b()        
        }a()

  function a() {
            var num = 5;
            alert(num) //5
            function b() {
                var num = 4;
                alert(num) //4
            }b();
        }a()

!在函数体内,局部变量的优先级高于同名的全局变量-作用域链
作用域链:内—外代码执行过程。

      var a=1;//全局的
         function fn(){
                 var a=2;//局部的//
                 console.log(a)//2
                 function fn1(){
                 var a=3;//局部的
                 console.log(a);//3从内到外寻找a的值输出
                     }
                 fn1();
                 }
                 fn();
                 console.log(a)//1

  var a = 2;
        function fn() {
            a = 4;//将之前a=2的值覆盖;
            b = 5;
            console.log(a);
            console.log(b);
        }
        fn()
        console.log(a);
        console.log(b)

2.JS的编译和执行

JS的解析过程分为两个阶段:预编译期(预处理)与代码逐行执行期。
第一阶段(预编译期):JS会对本代码块(script)中的所有声明的变量和函数进行处理(类似与C语言的编译,)但需要注意的是此时处理函数的只是声明式函数,而且变量也只是进行了声明但未进行初始化以及赋值。
第一阶段(预解析:浏览器编译执行代码之前,写完之后)
1、先找var和function关键字,如果找到var关键字,提前赋值undefined给变量名. 如果找到function,提前将整个函数赋值给函数名称。
2、如果函数和变量出现重名,函数优先。
3、函数的参数类似于变量,函数内部同样做预解析,支持预解析。
4、if语句和for语句里面的变量和函数做预解析提前赋值undefined
第二阶段(执行期):在编译后的基础上开始从上到下执行脚本,遇到错误时中断(函数声明直接跳过)。
例1

alert(a); //function a() {alert('不好');}//函数名和变量名重合,函数名优先
        var a = 1;
        alert(a); //1
        var a = 2;
        alert(a); //2
       
        function a() {
            alert('你好')
        }//函数未调用,直接跳过
        alert(a); //2

        function a() {
            alert('不好');

        }//函数未调用直接跳过
        alert(a); //2

例2
函数内部同样要做预解析。

*function fn(){
        alert(a);//undefined
       var a=1;
       alert(a);//1
}
     fn();*

例3
函数的参数类似于变量,函数内部同样做预解析,支持预解析。

var a = 1;
    function fn(a) {//a是函数fn的形参,在这里a被赋了值,函数的形参只能作用于函数体内部
        alert(a);//1
        a = 2;//重新给形参a赋值
        alert(a);//2
    }
    fn(a);
    alert(a);//1 函数体内,虽然给a重新赋了值,但是函数体内的参数无法在函数体外获取,故此处的a的值还是函数体外的a

例4
if语句和for语句里面的变量和函数做预解析提前赋值undefined

 function fn() {
            alert(a);//undefined
            if (false) {
                var a = 1;
            }
            alert(a)//undefined
        }
        fn()

例5

alert(fn);//fn为if函数里面的函数的函数名,if里面的函数和变量预解析,提前被赋值undefined
if (true) {
  function fn() {
    alert(1)
  }
}
alert(fn);// function fn() {alert(1)}//按顺序执行,函数名等于函数体,直接输出函数体

例6

 alert(a);// function a() {alert(1);},函数名和变量重名,函数优先,函数名等于函数体,输出函数体
        var a = 1;
        alert(a);//1

        function a() {
            alert(1);
        }//函数未被执行,因为未调用
        alert(a);//1
        a = 2;
        alert(a);//2
        var a = function() {
            alert(2);
        }//此处不是函数,是定义变量,属于赋值
        alert(a)//function() {alert(2);}

例7

 var a = 1;

        function b(a) {
            alert(a);//1,函数的形参a被赋了值,为1;
            var a = 2;
            alert(a);//2,a的值被覆盖了
        }
        b(a);//调用函数
        alert(a)//1无法获取函数内a的值,直接打印函数外的a的值

例8

 var x = 1;
        var y = 2;
        var z = 3;
        sum(x, y)//-1,第一个函数被第二个函数覆盖,无论在什么地方调用,都只会执行第二个函数

        function sum(x, y) {
            alert(x + y)
        }
        sum(x, y);//-1 第一个函数被第二个函数覆盖,无论在什么地方调用,都只会执行第二个函数

        function sum(x, y) {
            alert(x - y)
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值