• JavaScript入门学习之二——函数


    在前一章中讲了JavaScript的入门语法,在这一章要看看函数的使用。

    函数的定义

    JavaScript中的函数和Python中的非常类似,只不过定义的方式有些不同,下面看看是怎么定义的

    //定义普通函数
    function f1(){
        console.log('hello world!')
    }
    
    //定义带参数的函数
    function f2(a,b){
        console.log(a)
        console.log(b)
    }
    
    //定义带返回值的函数
    function f3(a,b){
        return a+b
    }
    
    //定义匿名函数
    var sum = function(a,b){
        return a+b
    }
    
    //定义立即执行函数
    (function(a){
        console.log('立即执行函数')
    })(a)

    立即执行函数其实有些像python里的lambda方法,的用法应该注意一下:因为在我们在全局内定义了一个变量,在定义函数的过程是无法调用这个变量的。

    (function(a,b){
        console.log(a+b);
        console.log('函数中')
    })(123,456)

    这个方法可以让外部访问不到函数中的变量,防止函数污染全局变量。

    函数的调用

    这里要将一个JavaScript里比较随意的一点(也可以说是一个坑),我们看一看下面的函数

    function fun(a,b){
        console.log(a+b);
    }
    
    fun(12,34)

    这样没啥问题,因为形参和函数调用的时候的实参数量是一致的。那么我们改一下实参的状态,会怎么样?

    fun(12,34,56)
    //打印值为46
    fun(12)
    //打印值为NaN

    arguments的使用

    这里就要讲到arguments的使用了,类似Python中的*args,arguments表达了函数的形参(但是是可以不用在声明函数中明确的写出来的)

    所以在JS的函数里不管是多传参数或少传参数都是不会报错的,我们可以这样看看

    function fun2(a,b){
        console.log(arguments)
        for (i=0;i<arguments.length;i++){
            console.log(arguments[i])
        }
    }
    
    fun2(11,22,33,44)

    而我们想要算一下传入参数的累加值,就要按下面的方法了

    function fun_sum(a,b){
        var totle=0;
        for (i=0;i<arguments.length;i++){
            totle += arguments[i]
        }
        return totle
    }
    
    console.log(fun_sum(1,2,3,4,5))
     函数的全局变量和局部变量

    局部变量

    在JavaScript内部声明的变量(var)是局部变量,所以只能在函数内部访问,就是说这个变量的作用域只有函数内部。只要函数运行完毕,改变量就会被删除。

    全局变量

    在函数外部声明的变量是全局变量,网页上所有的脚本和函数都能访问。

    var test = 'test'
    
    console.log('声明函数前',test)
    function fun(){
        console.log('开始声明函数',test);
        var test = 'in func';
        console.log('函数声明完成',test);
    }
    
    console.log('调用函数前',test);
    fun();
    console.log('调用函数后',test);
    
    //////////输出//////////
    声明函数前 test
    调用函数前 test
    开始声明函数 undefined
    函数声明完成 in func
    调用函数后 test

    注意这里还有个非常坑的点:

    我们在定义函数前有个变量test,如果在函数内部没有对这个test进行赋值,那么这个变量是正常的,但是一旦有了赋值操作,在操作前就成了underfined了(上面的例子就是有了赋值操作),在看看下面的

    var test2 = 123;
    function fun2(){
        console.log(test2)
    }
    
    fun2()
    
    //////////输出//////////
    123

    变量生存周期

    JavaScript的变量生命期从他们被声明的时候开始,

    局部变量是在函数运行结束的时候被删除,而全局变量是在页面被关闭的时候删除。

    作用域

    还是要看看这几个例子:

     例子1

    var city = 'beijing';
    function fun(){
        var city = 'shanghai';
        function inner(){
            var city = 'shenzhen';
            console.log(city);
        }
        inner();
    }
    
    fun()
    ////////输出////////
    shenzhen

    例子2

    var city = 'beijing';
    function fun(){
        console.log(city);
    }
    
    function fun2(){
        var city = 'shanghai';
        return fun;
    }
    
    var ret = fun2();
    ret();
    //////////输出//////////
    beijing

    案例3.闭包

    var city = 'beijing';
    function f(){
        var city = 'shanghai';
        function inner(){
            console.log(city);
        }
        return inner;
    }
    
    var ret = f();
    ret()
    
    //////////输出//////////
    shanghai

    在上面的例子中,ret对应的函数就是inner(),也就是闭包的用法。

    所以,函数的调用一定要往回找函数的定义过程。

    首先,在函数内部找->再往外部找,最后找全局作用域。

    词法分析

    JavaScript在调用函数的一瞬间,会先进行词法分析,大致过程是这样的:

    函数调用的前一个瞬间,回显形成一个激活对象:Active Object(AO),并会进行下面3个方面的分析

      函数参数——如果有参数,则将此参数赋值给AO,且值为underfined;如果没有,则不做任何操作。

      函数局部变量——如果AO上右同名的值,则不做任何操作,如果没有,则将此变量赋值给AO,并且值为underfined。

      函数声明——如果AO上有,则会将AO上的对象覆盖,如果没有则不做任何操作。

      综上所述,函数内部无论是使用参数还是使用局部变量都会到AO上找。

    再看看下面的例子:

    var name = 'xiaoming';
    var age =12;
    function fun(){
        console.log(age);
        var age = 30;
        console.log(age)
    }
    
    fun()
    
    //////////输出//////////
    underfined
    30

    这也就是讲了上面的那个坑是怎么导致的。

     1 var age =12;
     2 function fun(){
     3     console.log(age);
     4     var age = 22
     5     console.log(age)
     6     function age(){
     7         console.log('inner func');
     8     }
     9     console.log(age)
    10 }
    11 fun()
    12 //////////输出//////////
    13 ƒ age(){
    14         console.log('inner func');
    15     }
    16 22
    17 22

    结合前面的规则看看是怎么执行的。

    首先是分析过程:

      1.检查函数内是否有参数——没有

      2.检查函数内是否有局部变量——第4行的代码,定义了age局部变量,然后使AO.age=underfined

      3.检查函数内是否有内置函数——第6行的代码定义了局部函数age,然后覆盖原AO.age=fun()

    然后是执行阶段

      1.要记得,所有的值都是从AO里找的,第3行的打印就是打印的AO.age,实际值应为fun().

      2.第4行的代码是AO.age值赋值为22,后面再打印就是22了。

  • 相关阅读:
    浏览器原理
    jQ插件编写
    [转]清理浮动的全家
    百度面试~~
    LeetCode-222. Count Complete Tree Nodes
    LeetCode-236. Lowest Common Ancestor of a Binary Tree
    LeetCode-235. Lowest Common Ancestor of a Binary Search Tree
    LeetCode-102. Binary Tree Level Order Traversal
    LeetCode-404. Sum of Left Leaves
    LeetCode-257. Binary Tree Paths
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/12083357.html
Copyright © 2020-2023  润新知