数据类型(复杂数据类型)
函数 Function
1 . 函数的作用
存储代码,解决代码’复用’问题
2 . 函数的语法
- 2.1 声明函数:
function 函数名 ( ) {函数体 : 一段代码}
- 把代码存入内存中
- 函数在声明的时候是不会执行的
- 2.2 调用函数 :
函数名 ( )
- 执行函数体代码
3 . 易混淆的地方:
函数和循环的区别 : 两者毫不相干, 完全不同
- 循环 : 一段代码在一个地方执行多次
- 函数 : 一段代码在多个地方执行一次
4 . 需要使用函数的代码:
- 需要在多个地方执行(复用:重复使用)
- 一般都是独立的小功能
5 . 函数的参数
- 函数参数的作用: 调用者传值给函数
- 语法 :
- 传 : 调用者
函数名( 实际参数(数据) )
- 收 : 函数
函数名 ( 形式参数(变量) ) { 函数体 }
- 传 : 调用者
- 函数传参本质是赋值的过程: 实参给形参赋值
- 实参给形参赋值是按顺序一一对应
- 每一次传参的过程独立,互不影响(形参和实参可以不一致)
6 . 函数的返回值
- 返回值的作用: 函数 传递数据给 调用者
- 语法:
- 传 :
函数 : function 函数名( 形参 ) { 函数体 ; rsturn 返回值}
- 收 :
调用者 : let 变量名 = 函数名 ( )
- 传 :
- 为什么需要返回值: 因为不同的调用者,对函数运算结果的处理方式不同
- 例如 :有的调用者可能要把函数运算结果 发给服务器, 有的调用者可能要把函数运算结果在页面展示出来。
- 最合理解决方案是 : 函数将运算结果 交给调用者, 至于调用者如何处理结果,与函数无关
//1.声明函数
function getArrSum (arr) {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i]
}
//返回值
return sum
}
//2.调用函数
//调用者A
let sum1 = getArrSum([10, 20, 30, 40, 50])
console.log(sum1)//调用者A的需求是打印结果
//调用者B
let sum2 = getArrSum([88, 50, 90, 40])
document.write(sum2)//调用者B的需求是在页面展示
7 . 函数执行的三个流程
- 先传参 : 调用者 --> 函数 ( 实参给形参赋值)
- 执行函数体
- 返回值 : 函数 --> 调用者
8 . 返回值的注意点
- 写完 return 还要记得接收
- 如果函数没有 return ,默认的返回值是 undefined
- return 可以结束函数体执行 , return后面的代码不会执行
- return 和 break 的异同
- return 和 break 作用一样都是结束语句
- return 只能结束函数体
- break 只能结束循环和switch-case
9 . 函数的默认参数(逻辑中断,又叫短路运算)
- 什么叫做短路运算 : 如果逻辑表达式左边式子就可以决定结果,则右边式子编译器不执行
- 短路运算规则 :
&&
逻辑与 : 一假则假- 找假 :如果左边式子可以转换成false,无条件返回左边式子的值.反之无条件返回右边式子的值。
// 案例1 let res = 1 && 100 console.log(res) //100 // 案例2 let res2 = 1 && 2 && null && undefined console.log(res2) //null
||
逻辑或 : 一真则真- 找真:如果左边式子可以转成true,则无条件返回左边式子的值。反之无条件返回右边式子的值
// 案例1 let res1 = '' || 2 console.log(res1) //2 // 案例2 let res3 = 1 || 2 || null || undefined console.log(res3) //1
!
: 没有短路运算。 逻辑非只有一个式子
- 短路运算 ( 逻辑中断 ) 经典应用场景:函数默认参数
function fn (a, b) {
a = a || 10 //如果a有值,就返回a的值。反之返回10
b = b || 20//如果b有值,就返回b的值。反之返回20
console.log(a + b)
}
fn(55,80)// 135
fn(8) // 28
10 . 作用域
变量作用域 : 变量起作用的范围
- 全局作用域(全局变量) :在函数外面声明,页面任何地方都可以使用
- 局部作用域(局部变量) : 在函数内部声明,只能在函数内部使用
- 块级作用域 : 在大括号里面声明的变量(分支和循环),只能在大括号内部使用
//1.全局变量 : 全局作用域
let num = 10
function fn () {//函数的形参相当于在函数内部声明变量 : 局部变量
//2.局部变量: 局部作用域(函数内部作用域)
let age = 30
console.log(age)
}
fn()
for (let i = 1; i <= 10; i++) {
//3.块级变量:块级作用域(只能在大括号内部使用)
console.log(i)
}
11 . 作用域链
原理 : 默认情况下,js代码处于全局作用域(0级),当我们声明一个函数的时候,就会开辟一个局部作用域. 函数里面也可以声明函数,就会又形成局部作用域(2级),以此类推就会形成作用域链
//全局作用域(0级)
let num = 10
function fn () {
//局部作用域(1级)
let num = 20
console.log('1级作用域' + num)//20
function fn1 () {
//局部作用域(2级)
let num = 30
console.log('2级作用域' + num)//30
}
fn1()
}
fn()
console.log('0级作用域' + num)//10
变量在作用域链中的访问规则:就近原则
- 当你在某个作用域访问变量的时候,会先看当前作用域有没有声明。如果有则访问当前作用域的变量。没有就找上级,上级也没有就继续往上。直到作用域最顶端(0级),如果0级也没有,则程序会报错。
xxx is not defined
12 . 匿名函数
- 具名函数 : 有名字的函数
// 1.具名函数
// 函数式声明语法: function 函数名(){}
function fn () {
console.log(111)
}
// 函数调用
fn()
-
匿名函数 : 没有名字的函数
- 匿名函数可以用于赋值
// 匿名函数赋值 // 表达式声明 let 函数名 = 匿名函数 let f = function(){ console.log(2222) } f()
- 匿名函数可以自执行 :
(匿名函数)()
;//由于下面有匿名函数自执行,所以需要加分号 //匿名函数自执行 : 开辟独立作用域 (function(){ let num = 10 console.log(3333) })()
注意 : 匿名函数自执行,必须要加分号,才能开辟独立作用域