JavaScript函数进阶及作用域
Posted 橘猫吃不胖~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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!为例
5!–>54!
4! -->43!
3!–>32!
2!–>21!
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,在提升functi
例如:
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();// 调用函数
以上是关于JavaScript函数进阶及作用域的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript 精粹 基础 进阶函数和作用域(函数this)
JavaScript 开发进阶:理解 JavaScript 作用域和作用域链