JS中函数:
1.函数是什么 : 复杂数据类型
2.函数作用是什么 : 存储代码, 解决代码 '复用'
3.函数语法 :
3.1 存代码(声明函数 : 不会执行函数体 )
function 函数名(){
//函数体:一段代码
}
3.2 取代码执行( 调用函数: 执行函数体 )
函数名()
函数的传参:
/*
0. 函数 : 是一种 用于存储'代码块' 的复杂数据类型
* 作用: 解决代码‘复用’
1. 声明函数 : 存储代码过程,不会执行函数体代码
function 函数名(){
//函数体: 需要复用的代码
}
2. 调用函数 : 执行函数体代码
函数名()
3. 函数参数 : 调用者 传递数据给 函数
3.1 传数据 : 调用者
函数名(实参)
3.2 收数据 : 函数
function 函数名(形参){ //函数体 }
3.3 函数传参原理 : 实参给形参赋值
(1)函数传参是按照顺序 一一赋值
(2)每一次调用函数 传参过程都是独立的,互不影响
(3)函数实参 和 形参 数量 可以不一致
4. 函数返回值 : 函数 传递数据给 调用者
4.1 传 : 函数
function 函数名(){ //函数体 return 值 }
4.2 收 : 调用者
let 变量名 = 函数名()
4.3 返回值注意点 :
(1)return关键字后面的代码不会执行 (return可以结束函数体,类似于循环中的break)
(2)如果函数没有返回值,则得到是undefined (函数默认返回值是undefined)
没有返回值:
a. 没有写return
b. 写了return但是return后面没写值
*/
//1.声明函数
function learn(name,money) {
console.log(`1-${name}去玩耍了`)
console.log(`2-${name}去恰饭了`)
console.log(`3-${name}去搬砖`)
console.log(`4-${name}搬砖月薪${money}`)
}
//2.调用函数
console.log('小吴')
//调用者A
learn('小吴',15000)
//调用者B
console.log('小花')
learn('小花')// 底层 learn('小花',undefined)
//调用者C
console.log('小王')
learn('小王',8000)
//函数返回值例子:
//声明函数
function getSum(arr) {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i]
}
//返回值
return sum
}
/* 为什么要有返回值: 每一个调用者 对函数运算结果 的处理方式不同
解决方案: 函数本身不处理运算结果,而是交给 调用者 处理
*/
//调用函数
//调用者A
let sum1 = getSum([10, 20, 30, 40, 50])
//购物车页面 : 求和显示到button标签中
document.write(`<button>${sum1}</button>`)
//调用者B
let sum2 = getSum([80,90,20,55])
//订单统计 : 求和显示到h3标签中
document.write(`<h3>${sum2}</h3>`)
函数默认参数(逻辑短路):
/*
1.逻辑短路(逻辑中断) :
应用场景: (1)函数默认参数 (2)用于多条件筛选
1.1 逻辑与&& : 一假则假
找假。 如果左边式子为false,则返回左边式子的值。否则返回右边式子的值.
1.2 逻辑或|| : 一真则真
找真。 如果左边式子为true,则返回左边式子的值。 否则返回右边式子的值
2.函数默认参数 :
* 逻辑短路运算有很多的应用场景,函数默认函数是它的应用场景之一
*/
//(1)逻辑中断: 如果左边式子就可以决定逻辑表达式结果,则右边式子不执行
//(2)逻辑与 : 一假则假
//规则: 找假。 如果左边式子为false,则返回左边式子的值。反之返回右边式子的值.
let res = 10 && null
console.log( res )//null
//(3)逻辑或 : 一真则真
//规则: 找真。 如果左边式子为true,则返回左边式子的值。 反之返回右边式子的值
let res1 = 10 || null
console.log( res1 )//10
console.log( 20 && null && undefined )//null
console.log( 20 || null || undefined )//20
//逻辑非没有短路,因为逻辑非只有一个式子
/* 了解函数默认参数 */
function getSum(num1,num2){
num1 = num1 || 1
num2 = num2 || 2
let sum = num1+num2
console.log( sum )
}
getSum(10,20)//打印30
getSum(5)//打印NaN
作用域:
/*
1.变量作用域 : 变量可以使用的范围
2.js共有三种作用域
全局作用域(全局变量) : 在函数外面声明,可以在页面任何地方使用
局部作用域(局部变量) : 在函数内部声明的变量,只能在函数内部使用
块级作用域(块级变量) : 在大括号(分支+循环)里面声明的变量,只能在大括号内部使用
3.作用域链 : 默认情况下,代码处于全局作用域(0级),当我们声明一个函数之后,就会开辟一个局部作用域(1级),而函数内部又可以声明函数(2级),以此类推形成链式结构,称之为作用域链
4.作用域链访问规则 : 就近原则
* 当我们在作用域使用变量,优先看自己作用域有没有声明。如果有就用自己的,没有就找上级作用域,以此类推直到最顶级(0级),还找不到则报错 xxx is not defined
*/
//全局变量
let num = 10
//函数
function fn(a,b){
//局部变量
let age = 18
console.log( age )
}
// console.log( age )//报错. 局部变量只能在函数内部
fn(1,2)
//for循环
for(let i = 1;i<=6;i++){
console.log( i )
}
// console.log( i )//报错。 块级变量只能在大括号内部
console.log( num )//10
作用域链代码演示:
//全局作用域: 0级作用域
let num = 10
//函数
function fn(){
//局部: 1级作用域
let num = 20
console.log( num )//20
function fn1(){
//局部:2级作用域
let num = 30
console.log( num )//30
}
fn1()
}
fn()
console.log( num )//10
匿名函数:
/*
1.匿名函数 : 没有函数名的函数
* 匿名函数自调用 : ( function(){} )()
* 注意:自调用语法 前一个语句不能省略分号
2.匿名函数作用 : 开辟局部作用域,避免全局变量污染
* 全局变量污染 : 变量名太多了,会增加同名风险
*/
//具名函数: function 函数名(){}
function fn1(){
console.log(1111)
}
fn1()
//匿名函数(没有名字的函数无法直接调用) : function (){}
//1. let 函数名 = 匿名函数
let fn2 = function(){
console.log(22222)
}
fn2()
//2. 匿名函数自调用 ( function(){} )()
;(function(){
//局部作用域
let num = 10
console.log( num )
})()
高阶函数小拓展:
/*
1.任何数据类型共同点(值类型,引用类型)
* 都有变量赋值特点
2.引用类型特点
* 函数: 函数名()
* 数组: 数组名[下标]
* 对象: 对象名.属性名
*/
//函数
let fn = function(){
alert(1111)
}
//引用类型也是数据类型,也拥有变量赋值的特点
let a = fn
//函数语法: 函数名()
let res = fn()//返回值undefined
//数组
let arr = [10,20,30]
//引用类型也是数据类型,也拥有变量赋值的特点
let arr1 = arr
//数组语法 : 数组名[下标]
let num = arr[0]//10
//对象(明天讲解)
/* 高阶函数: 把函数作为参数 或 返回值 (函数也是数据类型,也可以赋值) */
function test(a){
console.log( a )
return function(){alert(1111)}
}
let b = test()