书写步骤
- 把核心代码写好
- 用function包裹
- 替换行参
- 考虑return
函数的优点:
- 实现了代码的可重用性
- 实现了模块化编程
预解析
流程:
- 查找
var
function
[即变量的定义、函数的定义] 提前存入内存中 分别赋值undefined
以及 代码段
[提升到所有代码的最前面] - 正式解读代码 在此过程中 略过变量与函数的定义
- 在变量赋值、函数调用时 它们在流程1时赋的值才会被实际赋值覆盖
[注意事项]
- 省略var定义的变量不会预解析
- 赋值式函数不会预解析
案例:
fn()
var fn=function(){
console.log('H,w!')
}
- 不会执行的代码段的内容也会进行预解析,因为预解析先于执行
- 预解析,出现同名函数和变量时,保留函数,忽略变量,因为函数定义隐形携带一个赋值的过程,变量不会重复声明进行覆盖
- 预解析只能在当前
<script></script>
中生效 不能跨script - 局部的预解析不能提升到全局
return关键字
情景1:将函数 内部的数据 返回给调用对象 提供给外部 后续代码 使用
案例:
function add(a, b) {
var sum = a + b
return sum //缺少本行后 变量c接受的数据为 undefined
}
var c = add(3, 2) // 5
特殊情景:递归函数
案例:
function jx(n) {
if (n == 1) {
return 1 //这是最后的return 值返回至上一个调用对象
}
return n * jx(n - 1) //return 1的值返回至此 该return返回上一次递归的return 直至返回到第一次递归前 该return返回出函数外
}
var res = jx(10)
console.log(res)
向下执行时 return没有生效 向上递归返回值时 return才生效
但是如果缺少return 递归函数可以向下执行 但是不能向上递归返回 即最终返回值为undefined
情景2:结束函数运行
案例:
function add(a, b) {
var sum = a + b
return sum
console.log(sum) //本行代码没有执行
}
var c = add(3, 2)
[注意事项] return只能返回一个值
案例:
function add(a, b, c) {
var sum1 = a + b //sum1 = 4
var sum2 = a + c //sum2 = 6
var sum3 = b + c //sum3 = 8
return sum1, sum2, sum3
}
var d = add(1, 3, 5)
console.log(d); // 8
默认返回一个且为最后一个值
匿名函数
定义:当函数作为值 赋给变量时 该函数的函数名可以省略
[赋值后 原函数名将不能被调用(not defined) 所以一般省略]
自调用函数:
定义:通过 在匿名函数后面 添加小括号 表示调用
[即函数定义好立即调用]
匿名单独存在会发生报错,自调用函数避免报错的方法:
1. 小括号包裹匿名函数:
(function(){
console.log('H,w!');
})()
2. 在匿名函数前添加感叹号:
!function(){
console.log('H,w!');
}()
3. 在匿名函数前添加波浪线:
~function(){
console.log('H,w!');
}()
匿名函数不能单独存在,否则报错
[即未命名 也未赋值]
作用域
全局变量:在函数外定义的变量
作用域:定义后的 所有文档区域 [整个script标签内]
[全局变量在页面关闭后删除]
局部变量:在函数内定义的变量
作用域:当前函数内部
[局部变量在函数运行后删除]
[每一个函数都是一个局部作用域]
[只有函数能生成局部作用域]
变量的 访问规则:
向上查找声明,直至全局作用域都没有 则报错
变量的 赋值规则:
向上查找声明,直至全局作用域都没有 则把该变量 定义为 全局变量 再赋值
[作用域的查找机制只能向上,不能向下]
[使用连等的方式定义变量并赋值时,只有第一个变量有定义,其余变量只有赋值]
案例:
function mF() {
var a = b = c = 9;
}
console.log(c); //变量c被定义为全局变量 成功打印9
console.log(b); //变量b被定义为全局变量 成功打印9
console.log(a); //变量a只在局部内定义 报错