1. 函数案例
// 声明函数
function getSum(a, b) {
return a + b
}
// 调用函数
let sum = getSum(1, 3)
console.log(sum) // 4
- 函数是实现特定功能的n条语句的封装体
- 函数类似于榨汁机,将苹果放进去,出来的是苹果汁
- 当一段代码需要多次执行时,考虑封装为函数(提高代码复用)
-
2. 两种声明方式
函数声明 ```javascript function sayHello(name) { console.log(‘Hello’ + name) // “Hello刘德华” }
sayHello(‘刘德华’)
- **函数表达式**
```javascript
const sayHello = function(name) {
console.log('Hello' + name) // "Hello刘德华"
}
sayHello('刘德华')
3. 参数
- 声明时可设置形参 ```javascript function printInfo(name, age) { console.log(name) console.log(age) } printInfo(‘刘德华’, 50) // 刘德华 50 printInfo(‘刘德华’) // 刘德华 undefined
// 默认参数
function printInfo(name, age=50) {
console.log(name)
console.log(age)
}
printInfo(‘刘德华’) // 刘德华 50
- **arguments对象**
- 使用arguments对象获取到该函数的所有传入参数
```javascript
function printInfo() {
console.log(arguments[0]) // "刘德华"
console.log(arguments[1]) // 50
console.log(arguments.length) // 2
}
printInfo('刘德华', 50)
/*
求任意个数参数的和
*/
function getSum() {
let sum = 0
for(let i = 0; i < arguments.length; i++) {
sum += arguments[i]
}
return sum
}
console.log(getSum(8)) // 8
console.log(getSum(1, 2)) // 3
console.log(getSum(1, 3, 4)) // 8
4. 返回值
- 使用return把结果导出
- 函数执行到return就立即终止
- 如果没设置return,默认返回的是undefined ```javascript
function printInfo() { console.log(1) // 1 console.log(2) // 2 return console.log(3) // 不执行 console.log(4) // 不执行 } printInfo()
function getSum(a, b) { let res = a + b // 没有return }
let result = sum(1, 4) console.log(result) // undefined
- **console.log() 和 return**
```javascript
function sum(a, b) {
return console.log(a + b) // console.log()的返回值是undefined
}
let res = sum(1, 4)
console.log(res) // undefined
5. 箭头函数
- 箭头函数简化了函数表达式
箭头函数和函数表达式有细微差异,体现在内部的this指代上
一个参数
/* const sayHello = function(name) { return 'Hello' + name } 等同于下面箭头函数 */ const sayHello = name => 'Hello' + name
/* 当函数体有多条语句时要加大括号 下面的箭头函数求数组元素之和 */ const getSum = arr => { let sum = 0 for(let val of arr) { sum += val } return sum } let arr = [1, 3, 5] let result = getSum(arr) console.log(result) // 9
多个参数 ```javascript / const getSum = function(a, b) { return a + b } 等同于下面箭头函数 / const getSum = (a, b) => a + b
```javascript
/*
function add(a) {
return function(b) {
return a + b
}
}
// 等价于下面箭头函数
*/
const add = a => b => a + b
let result = add(1)(5)
console.log(result) // 6
6. 函数命名
- 动词、动宾
- sum、hide、show
- printName、sayHello
- 返回一个非布尔值
- getData、getBooks
- 设置内容
- setInfo、setData
- 返回一个布尔值
- hasMoney、isEnabled
7. 声明前置
- var声明前置 ```javascript / // var a 提前 // var b 提前 var a a = 3 console.log(a) function doSomething() { var b console.log(b) b = 10 console.log(b) } doSomething() /
a = 3 console.log(a) // 3 var a function doSomething() { console.log(b) // undefined var b = 10 console.log(b) // 10 } doSomething()
- **function声明前置**
```javascript
fn1() // 正常执行
function fn1() {
console.log('fn1')
}
fn2() //会报错,函数表达式不会前置
const fn2 = function() {
console.log('fn2')
}
8. 运行环境
- 全局环境
- 函数环境
console.log('in 全局 start') foo() console.log('in 全局 end') function foo() { console.log('in foo') bar() function bar() { console.log('in bar') } }
9. 作用域链
- 函数在执行的过程中,先从自己内部找变量
- 如果找不到,再从创建当前函数所在的作用域(词法作用域)去找, 以此往上, 直到全局作用域
- 注意找的是变量的此刻的状态
let a = 0 function foo() { let a = 1 bar() } function bar() { console.log(a) // 输出0 } foo()
```javascript let a = 0 function foo() { bar() var a = 1 function bar() { console.log(a) // 输出undefined } } foo()let a = 0 function foo() { let a = 1 bar() function bar() { console.log(a) // 输出1 } } foo()
```javascript
let a = 1
function fn1(){
function fn2(){
console.log(a) // 输出2
}
function fn3(){
let a = 3
fn2()
}
let a = 2
return fn3
}
let fn = fn1()
fn()
10. 立即执行函数表达式(IIFE)
- 声明一个函数、立即执行它
- 意义:隔离作用域 ```javascript / (function() { //函数体 })() /
(function() { let a = 9 let b = 8 console.log(a + b) })()
(function () { var a = 1 function test() { console.log(++a) } window.$ = function() { // 向外暴露一个全局函数 return { test: test } } })()
$().test() // 2
<a name="Efduw"></a>
# 11. 递归
- 自己调用自己
- 设置终止条件
- 缺点:多次重复计算,性能差
```javascript
// 求阶乘
function fac(n) {
if(n === 1) return 1
return n * fac(n - 1)
}
let a = fac(3)
console.log(a) // 6
// 斐波那契数列
// 1 2 3 4 5 6
// 1 1 2 3 5 8 13
function fib(n) {
if(n === 1 || n === 2) return 1
return fib(n - 1) + fib(n - 2)
}
let a = fib(4)
console.log(a)
// 斐波那契数列
// 1 2 3 4 5 6
// 1 1 2 3 5 8 13
// 非递归方法
function fib(n) {
let first = 1, second = 1, temp
for(let i = 3; i <= n; i++) {
temp = first + second
first = second
second = temp
}
return second
}
let a = fib(6)
console.log(a)
12. 柯里化
- 柯里化
- 是把接受多个参数的函数变换成接受一个单一参数的函数
- 一个函数里返回一个新函数 ```javascript function add(a) { return function(b) { return a + b } }
let sum = add(3)(4) console.log(sum)
<a name="zwN3V"></a>
# 13. 回调函数
- 自定义
- 没有调用
- 最终执行了
```html
<button id="btn">回调函数</button>
<script>
let btn = document.querySelector('#btn')
btn.onclick = function() {
alert('dom事件回调函数')
}
setTimeout(function() {
alert('定时器回调函数')
}, 2000)
</script>