目录
一、函数简介
函数(Function)
- 也是一个对象。
- 它具有其他对象所有的功能
- 函数中可以存储代码,且可以在需要时调用这些代码
语法:
function 函数名(){ }
调用函数
- 调用函数就是执行函数中存储的代码
- 语法:函数对象()
使用 typeof 检查函数对象(typeof 函数名)时会返回 function 。
二、函数创建方式
函数的定义方式(三种方式):
1.函数声明
function 函数名(){
语句...
}
<script>
function fn(){
console.log('函数声明所定义的函数')
}
console.log(typeof fn)
</script>
2.函数表达式
const 变量 = function(){
语句...
}
注意:对于const 用 let 也行,主要看这个变量是否需要可以改对象
<script>
const fn = function(){
console.log('函数表达式')
}
console.log(typeof fn)
</script>
3.箭头函数(匿名函数,使用时应将其赋值给变量或常量)
()=>{
语句...
}
当箭头函数只有一条语句时,花括号可以省略。且当箭头函数只有一个参数时,括号可以省略
<script>
const fn3 = ()=>{
console.log('箭头函数')
}
const fn4 = ()=> console.log('箭头函数')//只有一条语句时,花括号可以省略
console.log(typeof fn3)
</script>
三、参数简介
形式参数(形参)
- 在定义函数时,可以在函数中指定数量不等的参数。
- 在函数中定义形参,就相当于在函数内部声明了对应变量,但是没有赋值
实际参数(实参)
- 在调用函数时,可以在函数的()传递数量不等的实参
- 实参会赋值给对应的形参
- 参数:
1.如果实参和形参数量相等,则对应的实参赋值给对应的形参;
2.如果实参多于形参,则多余的实参不会使用;
3.如果形参多余实参,则多余的形参被赋值为undefined.
参数的类型
- JS中不会检查参数的类型,可以传递任何类型的值作为参数。
1.函数声明
function 函数名([参数]){ // [ ] 表示可有可没有
语句...
}
2.函数表达式
const 变量 = function([参数]){
语句...
}
3.箭头函数(匿名函数,使用时应将其赋值给变量或常量)
([参数])=>{
语句...
}
练习:定义一个可以求任意两个数和的函数
<script>
function sum(a,b){
console.log(a + b)
}
sum(11,22)
</script>
四、箭头函数的参数和参数默认值
1.当箭头函数中只有一个参数时,可以省略()
<script>
const fn = (a,b)=>{
console.log('a = ',a)
console.log('b = ',b)
}
fn(1,43)
//当箭头函数中只有一个参数时,可以省略()
const fn2 = a =>{
console.log('a = ',a)
}
fn2(3)
</script>
2.定义参数时,可以为参数指定默认值,默认值会在没有对应实参时生效(不止在箭头函数中有效,在函数表达式和函数声明中也有效)。
<script>
//定义参数时,可以为参数指定默认值
const fn3 = (a=10,b=20,c=30) =>{
console.log('a = ',a)
console.log('b = ',b)
console.log('c = ',c)
}
fn3(1,2)
</script>
五、使用对象作为参数
对象可以作为参数传递
传递参数时,传递并不是变量本身,而是变量中存储的值
<script>
function fn(a){
a.name = '猪八戒'//修改对象时,如果有其他变量指向该对象,
//则所有指向该对象的变量都会受到影响
console.log('a=',a)
}
//对象可以作为参数传递
let obj = {
name:'孙悟空'
}
//传递实参时,传递并不是变量本身,而是变量中存储的值
fn(obj)
console.log('obj',obj)//obj与a指向同一对象,故通过a改变对象,则obj也改变
</script>
<script>
function fn(a){
a = {}//修改变量只会影响当前变量
a.name = '猪八戒'//修改对象时,如果有其他变量指向该对象,
//则所有指向该对象的变量都会受到影响
console.log('a=',a)
}
//对象可以作为参数传递
let obj = {
name:'孙悟空'
}
//传递实参时,传递并不是变量本身,而是变量中存储的值
fn(obj)
console.log('obj',obj)//只是修改a变量,故obj不改变
</script>
注意:如果直接将字面量和对象写为默认值,则函数每次调用都会重新创建默认值,但如果在外部书写,则每次调用是同一个对象
<script>
//在默认值处直接书写字面量
function fn2(a = {name:'沙和尚'}){
console.log('a=',a)
a.name = '唐僧'
console.log('a=',a)
}
fn2()
fn2()//第二次打印的是沙和尚、唐僧,说明两次调用的默认值不是同一个对象
//在外部写默认值
let obj3 = {name:'沙和尚'}
function fn3(a = obj3){
console.log('a=',a)
a.name = '唐僧'
console.log('a=',a)
}
fn3()
fn3()//第二次打印是唐僧、唐僧
</script>
六、函数作为参数
在JS中,函数也是一个对象(一等函数)。
别的对象能做的事情,函数也可以。
<script>
function fn(a){
console.log('a=',a)
a()
}
function fn2(){
console.log('我是fn2')
}
//将fn2函数作为参数
fn(fn2)
//直接将函数表达式作为参数
fn(function(){
console.log('我是匿名函数')
})
//直接将箭头函数作为参数
fn(()=>{
console.log('我是箭头函数')
})
</script>
七、函数的返回值
在函数中,可以通过 return 关键字来指定函数的返回值
返回值就是函数的执行结果,函数调用完毕返回值便会作为结果返回
<script>
function sum(a,b){
return(a + b)
}
function fn(){
return 122
}
let result = fn()
result = sum(12,32)//设置变量接收sum()函数返回值
result = sum(10,result)
console.log(result);
</script>
任何值都可以作为返回值使用(包括对象和函数之类)
如果return后不跟任何值,则相当于返回undefined
如果不写return,那么函数的返回值依然是undefined
<script>
function fn(){
// return {name:'孙悟空'}//返回对象
// return ()=>{
// alert(12)//返回函数
// }
return //如果return后不跟任何值,则相当于返回undefined
}
let result = fn()
console.log(result)
</script>
return一执行函数立即结束
<script>
function fn(){
alert(123)
return
alert(233)
}
fn()//不会执行alert(233)
</script>
八、箭头函数的返回值
箭头函数的返回值可以直接写在箭头后,前提是整个箭头函数只有一个语句
<script>
// const sum = (a,b) => {
// return a + b
// }
// let result = sum(12,23)
// console.log(result)
const sum1 = (a,b) => a + b//返回值直接写在箭头后,箭头函数只有一条语句
let result = sum1(12,23)
console.log(result)
</script>
如果直接在箭头后设置对象字面量({ })为返回值时,对象字面量必须使用括号括起来。因为对象是用{ }表示,而代码块也是用{ } 表示,当直接写对象字面量时,会将其认为是代码块。
<script>
const fn = () => ({name:'孙悟空'})//用括号括起来
let result = fn()
console.log(result)
</script>
九、全局和局部作用域
作用域(scope)
- 作用域指的是一个变量的可见区域
- 作用域有两种:
全局作用域
- 全局作用域在网页运行时创建,在网页关闭时销毁
- 所有直接编写到 script 标签中的代码都处于全局作用域中
- 全局作用域中的变量是全局变量,可以在任意位置访问
局部作用域(包含块作用域和函数作用域)
- 块作用域
-块作用域是一种局部作用域
-块作用域在代码块执行时创建,代码块执行完毕它就销毁
-在块作用域中声明的变量是局部变量,只能在块内部访问,外部无法访问
- 函数作用域
-函数作用域也是一种局部作用域
-函数作用域在函数调用时产生,调用结束后销毁
-函数每次调用都会产生一个全新的函数作用域
-在函数中定义的变量是局部变量,只能在函数内部访问,外部无法访问
十、作用域链
当我们使用一个变量时,
JS解释器会优先在当前作用域中寻找变量,
如果找到了则直接使用
如果没找到,则去上一层作用域寻找,找到了则使用
如果没找到,则继续去上一层寻找,以此类推
如果一直找到全局作用域都没找到,则报错xxx is not defined
<script>
let a = 10
{
let a = '第一代码块中的a'
{
let a = '第二代码块中的a'
console.log('a=',a)//就近原则,输出的是第二代码块中的a
}
}
</script>