概念: Function是一段被【预定义好的】,可以【反复使用】的代码,是独立的功能体,可以放入【若干】代码
适合放在函数中的内容:
- 不希望打开页面立即执行,等用户来触发
- 不希望执行一次,可以反复触发
- 本身就是一个独立的功能体
- 函数在js中具有第一等公民的地位,函数中的变量会自动释放
注意:
- 传入实参的顺序一定要和形参一一对应
- 函数不一定必须传入参数
- 若操作固定,则不需要传递参数
- 根据传入的参数不同,做的操作也略微不同,则需要添加参数
1.创建函数
- 声明方式:用function关键字进行声明,但只有变量/常量/函数具有声明方式
function 函数名(形参){函数体;return 返回值;}- 具有完整的声明提前
- 直接量方式
var 函数名=function(形参){函数体;return 返回值;}- 有声明提前,但赋值留在原地
- 构造函数方式
var 函数名=new Function("形参",...,"函数体")- 函数体在动态拼接时使用
调用函数
函数名(实参);var result=函数名(实参)
return
本意是退出函数,但若后面跟着一个数据,则可将数据返回到全局作用域,但仅返回并未保存,所以需要创建变量接住调用结果
- return只能写一次,最好写在函数体后面
- 何时使用:并不是任何时候都需要加return
- 全局想使用局部时
- 调用完函数还想拿到函数结果进行后续操作时
- 若无return,会有默认返回值undefined
2.作用域
- 全局:哪里都可以使用
- 函数:只能在函数调用时内部使用
- 变量的使用规则:优先使用局部,局部没有找全局,全局没有则报错
3.声明提前
在程序正式执行前,会将var声明的变量和function声明的函数集中提前到当前作用域顶部,但赋值留在原地
4.按值传递
- 原始类型之间 互不影响
- 引用类型之间 相互影响
5.重载
相同的函数根据传入的实参不同,会自动选择相应函数执行
- 目的:减少程序员负担
- 注意:js不支持重载,因为js不允许同时存在多个同名函数,最后一个会覆盖之前的所有函数
arguments
- 函数内部使用,类数组:下标、length、遍历
- 作用:可以借助实参,则不需要创建形参
- 使用arguments实现重载:通过判断arguments,实现功能
//传入一个实参做乘方,传入两个实参做加法
function f1(){
if(arguments.length==1){
return Math.pow(arguments[0],2);
}else if(arguments.length==2){
return arguments[0]+arguments[1];
}
}
console.log(f1(8));
console.log(f1(8,9);
6.匿名函数
无名字的函数,被没有变量名/函数名引用着,调用完毕后会立即释放
- 匿名函数自调
(function(){函数体;})() - 匿名函数回调:某个函数调用时,传入的实参是一个函数,且不需要调用执行
//例
arr.sort(function(a,b){return a-b;})
str.replace(reg,function(){})
- 匿名函数不是自调就是回调
7.闭包
函数的执行原理
① 程序在加载时:创建执行环境栈(ECS),首先压入全局执行环境(全局EC),全局EC中引用着全局对象window,window中保存着全局变量
② 定义函数时:创建函数对象,封装函数的定义。在函数对象中创建scope属性(记录自己来自的作用域)。全局函数的scope是window
③ 调用函数前:在执行环境栈中压入新的函数EC。创建活动对象AO,保存着本次函数调用时用到的局部变量。在EC中添加scope chain属性引用AO,设置AO的parent属性为函数的scope对象
④ 调用时:变量的使用规则是有限使用局部,局部没有找全局,全局没有报错
⑤ 调用完:函数的EC会出栈,AO会自动释放,故局部变量自动释放
作用域链scope chain
- 概念:以EC中的scope chain属性为起点,经过AO逐级引用,形成的一条链式结构,称为作用域链
- 作用:查找变量
闭包
- 概念:保护一个可以【反复使用的局部变量】的一种词法结构,结合了局部和全局的优点
- 使用步骤:
- 创建一个外层函数
- 在其中创建一个受保护的局部变量
- 外层函数调用要返回内层函数,此内层函数在操作受保护的变量
- 缺点:受保护的变量永远无法释放,用多了会导致内存泄漏
- 闭包的重点:
- 判断闭包,找到受保护的变量,确定其值
- 外层函数调用几次,就创建了几个闭包,受保护的变量就有了几个副本
- 同一外层函数调用,返回的内层函数,都是在使用同一个受保护的变量
//语法
function 外层函数(){
受保护的变量;
return function(){
不断操作受保护的变量;
return 结果;
}
}
var 内层函数=外层函数();
-
开发:防抖节流
- elem.onmousemove 鼠标移动事件,每次移动都会触发
- input.oninput input每次修改都会触发的事件
- window.onresize 屏幕每次改变大小都会触发
不会减少函数执行次数,但会减少DOM树渲染,DOM数据渲染的次数越频繁页面的效率越低下
//防抖节流
function fdjl(){
var timer=null;
return function(){
if(timer){clearTimeout(timer)}//判断有无定时器,有则清除
timer=setTimeout(function(){
操作;
},毫秒数)
}
}
var animate=fdjl();