1. 函数定义
函数的两种定义方式
1. 声明式定义函数
- 语法: function 函数名(){ 函数代码 }
+ function 关键字和 函数名 之间的空格不能省略
+ 函数名后面的小括号不能省略: 小括号中是写 形参
function fn() {
console.log('这是fn函数')
}
2. 赋值式定义函数----和之前讲的定义变量并赋值是一样
- 语法: var 变量名 = function (){ 函数代码 }
+ 赋值给变量的是一个没有名字的函数(匿名函数)
var ff = function () {
console.log('赋值式定义函数')
}
console.log(ff)
console.log(ff())
声明式与赋值式的区别
*
* 1. 写法不同
* 2. 调用上略有不同
* 声明式定义的函数, 可以在 函数定义前 去调用 (先不考虑原理)
* 赋值式定义函数, 不能再函数定义前 去调用
*
赋值式定义函数不能在函数定义前调用的原因
* 赋值式定义, 其实就是声明一个变量, 然后给他赋值为一个函数
* 在JS中, 如果在定义变量之前 使用变量的话, 那么变量的值为 undefined
*
* 函数的执行结果, 一般默认都是 undefined,除非手动更改
2. 函数调用
调用语法: 函数名() / 变量名()
返回值:函数的执行结果, 一般默认都是 undefined
声明式定义的函数
fn();
function fn() {
console.log( 'fn' )
}
fn();
赋值式定义的函数
ff();
var ff = function () {
console.log('ff')
}
ff();
注意: 在js中代码执行报错,会终止主程序的执行(报错之后的代码不会执行)
两种定义函数的方式 ,在函数调用时候的区别:
1)声明式定义的函数,可以在定义之前或者定义之后调用该函数
2)赋值式定义的函数,只能在定义之后调用该函数
函数的两个阶段(定义、调用)
1. 定义
=> 在堆内存开一个空间
=> 将函数的函数体内的代码 保存到堆内存中
=> 将堆内存的地址保存在变量名(函数名), 最后将这个变量名存储在栈内存中
2. 调用
=> 根据变量名(函数名)中的地址, 找到对应的函数
=> 然后再调用栈中开一个新的空间(函数的执行空间)
=> 在执行空间中 对函数的形参进行赋值
=> 在执行空间中 进行变量的预解析
=> 在执行空间中 执行函数的代码
=> 销毁当前函数的执行空间
案例1
var num = 666;
function ff() {
console.log( num )
}
var fn = function () {
console.log( num )
}
ff()
fn()
函数定义阶段:
1. 在内存中开辟一个空间(创建了一个盒子)
2. 将函数中的代码一模一样的放到这个空间中,此时不会解析函数中的变量num
- (相当于将函数中的代码,当做字符串一样放到开辟的空间中)
3. 将开辟的空间的 地址赋值给函数名ff/变量名fn
函数调用阶段:
1. 先根据函函数名ff/变量名fn中存储的地址,找到 函数代码的存储空间
2. 将函数存储空间中的代码拿出来执行,此时才会解析函数中的变量num,num=666
案例2
function fn() {
var num = 200;
console.log( num )
}
fn()
fn函数调用
根据fn中存储的地址,找到函数的存储空间 `0x001`
在运行内存中开辟一个函数的 执行空间 `0x00f`
将 `0x001` 中的代码拿过来在 执行空间 `0x00f` 中执行
将100赋值给变量num,控制台输出num的值100,函数代码执行结束
函数的执行空间 `x000f` 销毁
问题:
在函数执行空间中定义的变量num(或者函数的形参也是在该执行空间的变量)
随着执行空间的销毁 也 销毁了
如果在函数代码执行结束后,想要继续保存变量num ,如何实现?
如果函数的执行空间不销毁,则函数内的变量也不会销毁
3. 函数的参数
函数的参数分为两种
1. 形参
- 形参,在函数定义的时候 写到小括号中的变量----形式参数
+ 形参相当于在函数内部创建了一个变量, 变量实际的值由 "实参" 传递
+ 如果有多个形参,使用逗号分隔
2. 实参
- 实参,在函数调用的时候,写在小括号中的具体的数据,如果有多个也是用逗号分隔
+ 实参 在函数调用的时候,将自身的值, 按照一一对应的关系, 传递给 形参
函数形参赋值的注意事项:
1. 形参的数量如果大于实参
- 那么会将 实参按照顺序一一传递给 对应的形参
-多出来的形参, 相当于变量只定义没赋值, 所以他们的值 是 undefined
function fn(n, m, x, y) {
console.log(n, m, x, y)
}
fn(100, 200);
2. 实参的数量如果大于形参
-实参按照顺序 一一传递给对应的形参
- 多出来的实参,在函数内部不能通过 形参 得到这个实参的值
fn(10,20,30,40,50)
3. 函数内的arguments关键字,只能在函数内使用
- arguments接收了 所有 函数调用时候传递 的实参
function ff(n1,n2) {
console.log( arguments )
console.log( arguments[0] )
console.log( arguments[1] )
console.log( arguments[2] )
console.log( arguments.length )
}
ff(10,20,30,40,50,60);
函数参数的默认值
函数参数的默认值
函数再创建形参的时候, 默认给一个值, 将来在调用函数的时候,
如果没有传递,那么这个形参的值也不会是 undefined 而是给的默认值
如果传递了对应的值, 那么形参的值是实参传递进来的值, 否则按照默认值来运行
function fn(a = 100, b = '我是形参b', c) {
console.log(a, b, c)
}
fn(1) // 1 '我是形参b' undefined
4. 函数的返回值
函数内的关键字return
- 作用
1. return 会终止函数内代码的执行(return关键字,下一行的代码不会执行了)
function ff() {
console.log( 1 )
console.log( 2 )
return;
console.log( 3 )
console.log( 4 )
}
ff();
2. return 可以给函数创造一个返回值
1) return 关键字后面跟的是什么内容,函数调用返回的结果就是什么
function fn(a, b) {
var sum = a + b
return sum
}
var num = fn(50, 50)
console.log('num 的值: ', num)
2) return 关键字后如果什么都没写,则函数的返回值就是undefined
注意: 如果函数内没有return,则函数调用的返回值也是undefined
function fn(n) {
console.log( n+10 )
}
var res = fn(10);
console.log( res )