1、函数当成一个值的应用
- 直接赋值(定义一个变量,将函数赋值给变量,例如函数的创建中的一种方法:函数表达式语句 )
- 将函赋值给对象的属性
- 把函数作为数组中的某一项进行存储
//将函数赋值给变量
var a = function(a,b){
//函数体
}
//将函数赋值给对象的属性
var obj={
name:'leo',
fun:function(){
console.log('hello ' + this.name);
}
}
obj.fun();// hello leo
//将函数作为数组的某一项
var arr=[1,2,function(){return 2},'3'];
arr[3]; //'3'
2、将函数当成另外一个函数的参数来使用
例如数组的sort()方法可以接收一个函数,也称之为操作函数,没有时间差
var arr=[1,4,3];
arr.sort(function(a,b){
return a-b
})
console.log( arr ); //(3) [1, 3, 4]
3、将函数作为另一个函数的返回值进行使用
function a(){
var i=0;
return function(){
alert(i++);
}
}
var b = a();//此时b为一个函数
//第一次运行b(),弹出0,第二次运行b()喊出1,依次类推
4、闭包
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
//不使用闭包,str和i暴露在全局作用域下,很容易被修改或者影响
var str='abc';
var i=1;
function getId(){
return str+i++;
}
console.log(getId()); //abc1
console.log(getId()); //abc2
console.log(getId()); //abc3
//使用闭包
//函数a中return的函数就可以称之为一个闭包,全局作用域下无法访问函数体a中的str和i变量,a函数体内的函数可以访问到此变量
function a(){
var str='abc';
var i=1;
return function(){
return str+i++;
}
}
var getId=a();
console.log(getId()); //abc1
console.log(getId()); //abc2
console.log(getId()); //abc3
//简单写法,将函数a()设置为一个自执行函数,执行一次然后赋值给getId
var getId=(function(){
var str='abc';
var i=1;
return function(){
return str+i++;
}
})()
console.log(getId()); //abc1
console.log(getId()); //abc2
console.log(getId()); //abc3
console.log(str);//str is not defined
console.log(id);//id is not defined
//删除不用的闭包变量
getId=null;
函数正常的垃圾回收机制:函数运行完成后会将函数体内的变量及其他内容全部清理掉
闭包的垃圾回收机制:运行完成后变量不会被清理;
闭包缺点:由于闭包会使函数中的变量保存在内存中,内存消耗很大,所以不能滥用闭包,解决办法是,退出函数之前,将不使用的局部变量删除
作用域,作用域链
当定义一个变量时,会在当前作用域下查找此变量,如果没有则创建一个,如果有则忽略(在JS预处理过程实现,更准确的说是词法分析阶段实现此过程);
当运行代码时,如果是全局下运行,解释器会先创建一个全局的作用域,全局作用域下有一个列表,此列表称之为作用域链,作用域链上包含一个对象,此对象称之为活动对象。
在全局运行时,作用域链只包含一个活动对象;如果是在函数中运行,函数 定义时 就包含了一个作用域链,此作用域链只包含一项,全局活动对象,当函数 运行时 ,会创建一个新的活动对象推入到定义时的活动对象中,此时函数所对应的活动对象就包含两个。
函数外部为什么不能查找函数内部变量?
1、函数的作用域链与函数外的作用域链没有交集
2、函数上的作用域链在函数执行完成已经被删除
备注:本内容学习总结来源于喜马拉雅冰山工作室沙翼老师主讲的(陪你读书(JavaScript WEB前端))