美文网首页
js function的运行机制

js function的运行机制

作者: 路上灵魂的自由者 | 来源:发表于2019-01-07 18:36 被阅读10次

    // 引用类型的特殊的 函数类型

    /*

    * 在js中,函数就是一个方法(一个功能题),基于函数一般都是为了实现某个功能

    * 函数诞生的目的就是为了实现封装:把实现一个功能的代码封装到一个函数中,后期想要实现这个功能,只需要把函数执行即可,不必再次编写重复的代码,起到了”低耦合高内聚(减少页面中的冗余代码,提高代码的重复使用率)“

    * 创建函数 function fn(){ }

    * 执行 fn()

    */

    /*

    ES3标准中:

    //=>创建函数

        function 函数名([参数]){

            函数体:实现功能的js代码

        }

    //=>函数执行

        函数名();

    */

    // ===

    /*

    ES6标准中创建箭头函数

    //=>创建函数

        let 函数名(变量名)=([参数])=>{

            函数体

        }

    //=>函数执行

        函数名();

    */

    /*

    * 函数的运作机制

    * 函数作为引用数据类型中的一种,它是按照引用地址来操作的。

    function fn(){

        var obj = 10;

        total+=10;

        total=total.toFixed(2)

        console.log(total)

    }

    * 【创建函数】

    * 1.函数也是引用类型,首先会开辟一个新的堆内存,把函数体中大代码当做”字符串“存储到内存中(对象向内存中存储的是键值对)

    * 2.把开辟的堆内存地址赋值给函数名(变量名)

    * 此时我们输出fn(切记不是fn())代表函数本身,如果我们执行fn(),这是把函数执行,所有是否加小括号是两种不同本质的操作

    * 【函数执行】

    * 目的: 把之前存储到堆内存中的代码字符串变为真正的js代码自上而下执行,从而实现应由的功能

    *1.函数执行,首先会形成一个私有的作用域(一个供代码执行的环境,也就是一个栈内存(私有占内存))

    *2.把之前的堆内存中存储的字符串复制一份过来,变为真正的js代码,在新开辟的作用域中自上而下执行;

    */

    函数运行的机制

    // 函数中的参数

    // 参数是函数的入口:当我们在函数中封装一个功能。发现一些原材料不确定,需要执行函数的时候用户传递进来的才可以,此时我们就基于参数的机制,提供出口即可

    function sum(a,b){ //此处的参数叫做形参:入口,形参就是变量

    return a+b

    }

    //此处的参数叫做实参:实参就是值

    sum(10,12)  // =>n=10,m=20

    sum(10);    // =>n=10,m=undefined

    sum(10,20,30) //=>n=10,m=20,30没有形参变量接受

    // 函数(function)

    function fn1(n,m) {  //=>形参:入口

        // =>函数体

        var total = 0; // total: 私有变量

        total = n + m;

        console.log(total)

    }

    fn(10,20)  //=>实参:给形参传递的具体值

    var a = 12;

    fn(a,1===1?10:0)  //=》实参一定是值,即使我们写的变量或着表达式,也是把变量或者表达式计算的结果作为中传递给形参变量

    // console.log(total)  //total是私有变量,我们无法在函数外面获取这个值(闭包)

    // 函数执行的时候形成一个全新私有作用域(私有栈内存),目的是:

    1,把原有堆内存中存储的字符串变为js表达式执行。

    2.保护里面的私有变量不受外界的干扰(和外界是隔离的),我们把函数执行的这种保护机制,称之为”闭包“。

    /*

    * 函数的入口: 形参

    * 函数的出口,返回值 return

    * 出口的作用:把函数运行的结果(或者函数体中的部分信息)拿到函数外面取使用

    */

    function fn2(n,m) { 

        var total = 0;

        total = n + m;

        return total;  //=>并不是把total变量返回,返回的是变量存储的值返回,return返回的永远是一个值

    }

    fn //=>代表的是函数本身

    fn(10,20) //=>代表的是函数执行(不仅如此,他代表的是函数执行后,返回的结果(return返回的值))

    var result = fn2(1,2);

    console.log(result,1)  //=>3

    function fn3(n,m){

        var total = 0;

        total = n + m;

        // return total;

    }

    var res = fn(100,200);

    console.log(res);      //undefined

    function fn(n,m){

        // =>如果n/m又一个没有传递值,我们返回零

        if(n===undefined || m===undefined){

            return 0; //=》 return还有一个作用,类型域循环中的break,能强制结束函数体中代码的执行(return后面的代码不在执行)

        }

        var total = 0;

        total = n + m;

        return total;

    }

    console.log(fn(10))

    // n==undefined 经常这样判断n的值是否为undefined,这种方式可以

    // n==undefined 这种模式不好,因为null==undefined也是相等的(===比较才不相等)

    typeof n == 'undefined' // 真实项目中经常用这种方式

    // total = 0;  0是有值的,从内存方面来说,会在栈内存中占一个位置

    // total = null;  一般更喜欢用null作为初始值。null是空对象指针,是不占内存位置的。

    // arguments 

    /*

    * 任意数求和:不管函数执行的时候,传递多少实参进来,我们都可以求和

    *

    * 形参是有局限性,我们需要具体知道用户执行的时候传递实参数量。。顺序等,才可以使用形参变量定义对应入口

    * arguments : 函数内置的实参集合(内置:函数天生就存在的机制,不管你是否设置了形参,也不管你是否传递了实参,ARGUMENTS都有,始终存在);

    */

    function sum1(n,m){

        console.log(arguments)

        console.log(arguments.callee == sum)  //true

        // {

            // '0': 10,

            // '1': 20,

            //  length: 2,

            //  callee: 当前函数本身

        // }

    /*

        * arguments它是一个类数组(不是数组,不能用数组里面的方法)

        * 即使设置形参变量,形参变量该是什么值还是什么值,但是Arguments使用存储的是“所有”传毒进来的实参,所以他被称为“实参集合”

    */

    }

    /* 

     *   把arguments的实参值依次遍历,每遍历一个都累计起来,最后实现任意数求和

     */

    //ES5写法

    function sum2(){

        var total = null;

        for(var i = 0;i<arguments.length;i++){

            var item = arguments[i]

            total+= item;

        }

        return total;  //把结果返回

    }

    console.log(sum2(10,20,30))

    console.log(sum2(10,20,30,40))

    // =>升级:在累加的时候,把字符串转换为数字,对于一些非有效数字,不在相加

    function sum(){

        var total = null;

        for(var i = 0;i<arguments.length;i++){

            var item = arguments[i]; 

            // 1.不光ITEM获取的是传递的啥,都先转换为数字类型

            item = Number(item)

            isNaN(item)?null:total+=item

        }

        return total;  //把结果返回

    }

    console.log(sum(10,20,'30','AA',40,50))

    console.log(sum(10,20,30,40))

    //ES6写法

    let sum = (...arg) =>{

        arg=arg.filter(item=>!isNaN(item));

        return eval(arg.join("+"))

    }

    console.log(sum(10,20,'30','AA',40,50))

    // 实名函数与匿名函数

    /*

    * 实名函数:有函数名的

    * 匿名函数:没有函数名的

            -函数的表达式:把函数当作值赋值给变量或者元素的事件

            -自执行函数:创建和执行一起完成的

    */

    // 匿名函数

    // =》函数表达式

    /*var fn = function(){

    };

    oBox.onclick= function(){

    } */

    // =>自执行函数

    (function (i) {})(10);

    ~function () {}();

    +function () {}();

    !function () {}();

    相关文章

      网友评论

          本文标题:js function的运行机制

          本文链接:https://www.haomeiwen.com/subject/jfzurqtx.html