js function的运行机制

2019-01-07  本文已影响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 () {}();

上一篇下一篇

猜你喜欢

热点阅读