1.定义一个函数(函数是一个对象)
1.具名函数
function fn(a,b){return a+b}
2.匿名函数(也叫函数表达式)
let fn = function(a,b){return a+b}
3.箭头函数
let fn = (x,y) =>{return x+y}
let fn = (x,y) =>{name:x,age:y};这样直接返回对象有问题,需要加上小括号
let fn = (x,y) =>({name:x,age:y})
4.构造函数
let fn = new Function('X','Y','return X + Y ')
基本没人用,但是要知道每一个函数都是Function构造出来的
2.函数调用
let fn = () => console.log('hi')
let fn2 = fn
fn2()
理解:
- fn保存了匿名函数的地址
- 这个地址又给复制给fn2
- fn2()调用了匿名函数
- fn、fn2都是匿名函数的引用而已
- 真正的函数既不是fn又不是fn2
3.函数的要素
每个函数都有这些东西:
- 调用时机
- 作用域
- 闭包
- 形式参数
- 返回值
- 调用栈
- 函数提升
- arguments(除了箭头函数)
- this(除了箭头函数)
1.调用时机
时机不同,结果不同
(1)
let a = 1
function fn(){console.log(a)}
fn() //1
** (2)**
let a = 1
function fn(){console.log(a)}
a = 3
fn() //3
(3)
let a = 1
fuction fn (){
** setTimeout(()=>{console.log(a)},0)**
}
fn()
a=2
输出2,因为setTimeout要等这些执行完再调用
2.作用域
每一个函数都会默认创建一个作用域
function fn(){let a = 1}
fn()
console.log(a)
即使调用了也访问不到
3.闭包
一个函数用到的外部的变量,那他就是闭包
4.形式参数
就是非实际参数
形参可认为变量声明
function fn(a,b){return a+b}
相当于
function fn(){
var a = arguments[0]
var b = arguments[1]
return a+b
}
5.返回值
- 每一个函数都有返回值
- 函数执行完了才会返回
- 只有函数有返回值(数字相加的返回,叫做值,不叫返回值)
(1)
function(){
console.log('hi')
}
fn()
没写return,所以返回值是undefined
(2)
function(){
return console.log('hi')
}
fn()
返回值还是undefined,返回的是console.log('hi')函数的值
6.调用栈
- JS引擎在调用一个函数前
- 需要把函数所在的环境push到一个数组里
- 这个数组叫做调用栈
- 等函数执行完,就会把函数弹出来(pop)
- 然后return到之前的环境,运行后续的代码
7.递归
求阶乘
function(n){
return n !== 1 ? n*fn(n-1) : 1
}
先递进,在回归
8.函数提升
不管把具名函数放在哪一行,它都会自动到第一行
let fn = function(){};这个不会提升,这是赋值
9.arguments和this
如何传arguments
调用fn函数,即可传arguments
fn(1,2,3),那么arguments就是[1,2,3]伪数组
如何传this
fn.call(xxx,1,2,3)
xxx会自动转换为对象
let perpon = {
name : 'frank',
sayHi(){
console.log(我的名字是+this.name)
}
}
perpon.sayHi.call(perpon);调用加上call,指向自己
即使没有用到this,也要写call,指向undefined,null也行