声明函数
声明函数的常见方式
具名函数
function name(param) { functionBody }
匿名函数
function (param) { functionBody }//因为没有名字,所以一般是函数解析完自执行或者用变量接收它function (param) { functionBady}()let fn = function (param) { functionBady}
箭头函数
(param)=>{ functionBody }
构造函数
new Function (param, param, functionBody)
调用()
我们知道如何声明函数,那如何使用它呢?
let fn = () => console.log("hi")声明函数undefined//返回值//下面是函数调用fn()//调用hi //控制台打印undefined//返回值fn2 = fnfn2()//hi//undefined如上代码,fn保存了匿名函数的地址,这个地址被复制给了fn2,fn2()调用了匿名函数。fn和fn2都是匿名函数的引用而已,真正的函数既不是fn也不是fn2。
关于函数
作用域&&闭包
全局作用域
- 在顶级作用域声明的变量是全局变量
- window的属性是全局变量
- 其它的都是局部变量
- 显式声明:
带有关键字 var 的声明;我们写的函数如果不经过封装,也会是全局变量,他的生命周期也就是全局作用域;
- 隐式声明:
不带有声明关键字的变量,JS 会默认帮你声明一个全局变量!!!
块级作用域
函数作用域内,对外是封闭的,从外层的作用域无法直接访问函数内部的作用域。
需要用 let 和 const 关键字声明
通过 return 访问函数内部变量
静态作用域和词法作用域
JS 里面除了 this 都是静态作用域或者词法作用域
规则:
如果多个作用域有同名变量a,那么在查找a时,就向上取最近的作用域——就近原则
闭包
形参
返回值
每个函数都有返回值,默认返回undefined,也可以指定。
压栈&&弹栈&&爆栈
压栈:JS引擎在调用一个函数前,需要把函数所在的环境push到一个数组里,这个数组就叫做调用栈或者叫压栈
弹栈:等函数执行完了,就会把环境弹(pop)出来(弹栈),然后return到之前的环境,继续执行代码
爆栈:内存中调用栈存储信息有限,递归情况下,如果递归层次过深会导致调用栈耗光而引起stack overflow
Chrome:11434二分法试出来的。
递归
函数提升
通常JS引擎会在正式执行之前先进行一次预编译,在这个过程中,
首先将变量声明及函数声明提升至当前作用域的顶端,然后进行接下来的处理。
声明和赋值是不一样的!
