JavaScript函数进阶及作用域

1 函数表达式

函数表达式:是将声明的函数赋值给一个变量,通过变量完成函数的调用和参数的传递,函数表达式的定义必须在调用前。

示例:

var sum = function (num1, num2) {// 函数表达式
    return num1 + num2;
};
console.log(sum(1, 2));// 调用函数

结果是:3

2 回调函数

回调函数:指的就是一个函数A作为参数传递给一个函数B,然后在B的函数体内调用函数A。此时,称函数A为回调函数。

示例:

function cal(num1, num2, fn) {
    return fn(num1, num2);
}
var s1 = cal(45, 55, function (a, b) {
    return a + b;
})
console.log(s1);

结果为:
100

程序运行思想如下:

1、从console.log(s1);开始,函数要输出s1的值
2、s1调用cal,并给cal函数传入了3个值,分别是45,55,function(a,b)
3、45传给了num1,55传给了num2,function(a,b)传给了fn
4、在cal函数中,返回值重新返回了fn,并将给cal函数传入的num1=45,num2=55传给了fn(num1,num2),得到function(45,55)
5、回到s1的计算中,此时的s1为cal(45, 55, function (45,55)),返回a+b的值即45+55的值,赋值给s1
6、最后得出结果s1的值为100

3 递归调用

递归调用:指的是一个函数在其函数体内调用自身的过程,这种函数称为递归函数。

用递归解决问题条件:
1、问题可以分解,分解后得到的新问题的解法与原问题的解法相同
2、分解的过程要有明确的结束条件

递归的过程:
1、自上而下分解问题:以计算5!为例
在这里插入图片描述
2、自下而上回溯得到问题的解
1!–>2!–>3!–>4!–>5!

示例:使用递归求1+2+3+…+100的值

function getSum(n) {
    if (n == 1) {
        return 1;
    } else {
        return n + getSum(n - 1);
    }
}
console.log(getSum(100))

结果是:5050

该程序的思想为:

1、定义一个函数,参数值为n,n为要求的前n项的和的数字,这里将传入100
2、当n等于100时,即getSum(100),返回值为100加getSum(99),getSum(99)为99加getSum(98),…,依次类推
3、当递归到3+getSum(2)时,getSum(2)为2加getSum(1),当n为1时,返回值为1,即getSum(2)为2+1,getSum(3)为3+2,…,getSum(100)为100+99
4、最后整个函数就实现了100+99+98+……+1的效果

4 作用域

变量需要在它的作用范围内才可以被使用,这个作用范围称为变量的作用域, JavaScript根据作用域使用范围的不同,划分如下:

全局变量(全局作用域):不在任何函数内声明的(在函数外部定义的)变量(显式定义)或在函数内省略var声明的变量(隐式定义)都称为全局变量。全局变量在浏览器页面没有关闭之前一直占用内存空间,比较耗费内存,在浏览器页面关闭时才释放内存。

例如:直接在函数外部定义

var i = 0;//显式定义

或者在函数内部不加var定义:

function fun() {
    i = 0;//隐式定义
}

局部变量(局部作用域):在函数体内利用var关键字定义的变量称为局部变量。局部变量只在函数内部起作用,函数调用结束后,局部变量所占的内存就会被释放。

例如,在函数内部定义:

function fun() {
    var i = 0;//在函数内部定义
}

块级变量:ES6提供的let关键字声明的变量称为块级变量

示例:

for (let i = 0; i < 100; i++) {
    //函数体代码
}

全局变量和局部变量两者的区别:
1、在全局作用域下,添加或省略var关键字都可以声明全局变量,全局变量在浏览器关闭页面的时候才会销毁,比较占用内存资源;
2、在函数中,添加var关键字声明的变量是局部变量,省略var关键字时,如果变量在当前作用域下不存在,会自动向上级作用域查找变量。局部变量在函数执行完成后就会销毁,比较节约内存资源

作用域链:当在一个函数内部声明另一个函数时,内层函数只能在外层函数作用域内执行,在内层函数执行的过程中,若需要引入某个变量,首先会在当前作用域中寻找,若未找到,则继续向上一层级的作用域中寻找,直到全局作用域,称这种链式的查询关系为作用域链。

5 闭包函数

5.1 什么是闭包函数

所谓“闭包”指的就是有权访问另一函数作用域内变量(局部变量)的函数。主要的两点用途如下:
1、可以在函数外部读取函数内部的变量
2、可以让变量的值始终保持在内存中

注意:由于闭包会使得函数中的变量一直被保存在内存中,内存消耗很大,所以闭包的滥用可能会降低程序的处理速度,造成内存消耗等问题。

5.2 闭包函数的实现

闭包的常见创建方式就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量,可以在函数外部读取函数内部的变量。

示例:

function fn() {
    var times = 0;
    var c = function () { return ++times; };
    return c;
}
var count = fn(); // 保存fn()返回的函数,count就是一个闭包
console.log(count());	// 输出结果:1
console.log(count());	// 输出结果:2
console.log(count());	// 输出结果:3  

6 预解析

JavaScript解析器在运行JavaScript代码的时候会进行预解析,也就是提前对代码中的var变量声明和function函数声明进行解析,然后再去执行其他的代码。

把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。

先后规则:先提升 var,再提升function

例如:

console.log(num);// 输出结果:undefined
var num = 10;
console.log(num2);// 报错,提示 num2 is not defined

这段代码会先将var进行预解析,就是:

var num ; // undefined
console.log(num) ;
num  = 10;

例如:

var a = 25;
function abc() {
    console.log(a);
    var a = 10;
}
abc();//结果为:undefined

预解析结果:

var a; // 在全局作用域里提升变量
function abc() { // 在全局作用域里提升函数
    var a; // 在局部作用域里提升变量
    console.log(a); // a的值是 undefined
    a = 10; // 在局部作用域里给变量赋值
}
a = 25; // 给变量赋值
abc(); // 调用函数
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值