声明函数

声明函数的常见方式

具名函数

  1. function name(param) { functionBody }

匿名函数

  1. function (param) { functionBody }
  2. //因为没有名字,所以一般是函数解析完自执行或者用变量接收它
  3. function (param) { functionBady}()
  4. let fn = function (param) { functionBady}

箭头函数

  1. (param)=>{ functionBody }

构造函数

  1. new Function (param, param, functionBody)

调用()

我们知道如何声明函数,那如何使用它呢?

  1. let fn = () => console.log("hi")声明函数
  2. undefined//返回值
  3. //下面是函数调用
  4. fn()//调用
  5. hi //控制台打印
  6. undefined//返回值
  7. fn2 = fn
  8. fn2()
  9. //hi
  10. //undefined
  11. 如上代码,fn保存了匿名函数的地址,这个地址被复制给了fn2fn2()调用了匿名函数。
  12. fnfn2都是匿名函数的引用而已,真正的函数既不是fn也不是fn2

关于函数

作用域&&闭包

全局作用域

  1. 在顶级作用域声明的变量是全局变量
  2. window的属性是全局变量
  3. 其它的都是局部变量
  • 显式声明:

带有关键字 var 的声明;我们写的函数如果不经过封装,也会是全局变量,他的生命周期也就是全局作用域;

  • 隐式声明:

不带有声明关键字的变量,JS 会默认帮你声明一个全局变量!!!

块级作用域

函数作用域内,对外是封闭的,从外层的作用域无法直接访问函数内部的作用域。
需要用 letconst 关键字声明
通过 return 访问函数内部变量

静态作用域和词法作用域

JS 里面除了 this 都是静态作用域或者词法作用域
规则:
如果多个作用域有同名变量a,那么在查找a时,就向上取最近的作用域——就近原则

闭包

一个函数用到它外部的变量,那么 这个函数+变量=闭包

形参

形参可认为是变量声明
传参:将实参的值和地址复制给形参

返回值

每个函数都有返回值,默认返回undefined,也可以指定。

压栈&&弹栈&&爆栈

压栈:JS引擎在调用一个函数前,需要把函数所在的环境push到一个数组里,这个数组就叫做调用栈或者叫压栈
弹栈:等函数执行完了,就会把环境弹(pop)出来(弹栈),然后return到之前的环境,继续执行代码
爆栈:内存中调用栈存储信息有限,递归情况下,如果递归层次过深会导致调用栈耗光而引起stack overflow
Chrome:11434二分法试出来的。

递归

递进回归,函数在内部自己调用自己。

函数提升

通常JS引擎会在正式执行之前先进行一次预编译,在这个过程中,
首先将变量声明及函数声明提升至当前作用域的顶端,然后进行接下来的处理。
声明和赋值是不一样的!