函数的作用
- 解决代码冗余问题,提高代码复用率
- 实现代码的模块化
- 封装代码,是函数内部代码对外部不可见
函数三要素
- 函数名,最好使用动词,经常使用
get
,set
作为前缀 - 参数,定义函数是括号内的为形参,调用函数时传递实参,形参一般是变量,实参是具体的值
- 返回值,函数通常会通过
return
返回值作为函数调用表达式的值,若无return
默认返回undefined
- 函数是否需要参数和返回值需要具体判断
函数的使用
字面量定义
js
funcation funcName (argument1, argument2) {
statement;
}
表达式定义
js
var funcName funcation (argument1, argument2) {
statement;
}
函数调用
js
funcName(value1, value2); //函数调用表达式
console.log(funcName(value1, value2)); //控制台直接输出返回值
var result = funcName(value1, value2); //使用变量存储返回值
函数实参伪数组
- 每个函数内部都会有一个名为
arguments
的实参伪数组 - 可以通过
arguments.length
获取参数个数,arguments[i]
获取第i
个参数
函数作用域
- 作用域表示变量起作用的范围,主要用来隔离变量(函数外部与函数内部的同名变量没有关系)
- 通常情况函数外部是全局作用域,函数内部是局部作用域(函数作用域)
- 全局作用域中的变量称为全局变量,局部作用域中的变量称为局部变量
- 全局变量可以在函数内部操作,但局部变量无法在全局作用域中操作
- 特殊情况 在函数内部的变量没有使用
var
关键字时:- 首先判断该变量是否是形参,是形参作为局部变量处理
- 若该变量不是形参,判断全局作用域中有无该变量,有则直接操作全局变量
- 若全局作用域中无该变量,则相当于在函数外部定义新的全局变量
- 作用域在函数定义时就已经确定了
作用域链
- 作用域链指的是变量通过一定的规则去查找,查找的过程称为作用域链:
- 先从自己的作用域中查找,找不到则去上级作用域查找,找到该变量则不再继续查找
- 若直到全局作用域都没有找到,则会报错(提示变量未定义)
- 作用域链在函数调用时才会存在,每个执行环境都有自己独立的作用域链
预解析(变量提升)
- 代码执行之前会进行预解析,域解析会解析所有包含
var
关键字的变量和函数: - 预解析时函数优先级比变量要高,先解析所有的函数,再解析变量:
- 函数重名,后面的覆盖前面的
- 变量重名,会忽略后面的变量
- 字面量定义函数,整个函数被提升
- 表达式定义函数,只提升变量(函数当做使用
var
关键字的变量) - 没有
var
关键字的变量不是进行预解析
立即调用函数表达式
js
(function() {
console.log("hello function!");
})();
IIFE
全称Immediately Invoked Function Expression
,中文立即调用函数表达式,别名匿名函数自调用表达式- 声明函数的同时会立即调用这个表达式,特点:
- 函数只执行一次
- 定义的同时执行
- 函数不参与预解析,但函数内部会进行预解析
- 作用:
- 隐藏代码实现,只向外部暴露必要部分,封装插件可能用到
- 防止外部命名空间被污染
- 对项目进行初始化
函数的递归调用
- 一个函数在内部又调用了自身称为函数的递归调用
- 函数的递归调用比较消耗内存,使用时应该注意:
- 必须有一个明显的结束条件
- 必须有一个趋近结束条件的趋势
求阶乘
js
function getFactorial(n) {
if (n <= 1) {
return 1;
}
return n * arguments.callee(n - 1);
}
回调函数
- 定义一个函数后,没有调用,但是函数却执行了,这种函数称为回调函数
- 回调函数一般都是作为参数传递的
- dom 事件多为回调函数