作用域
JavaScript采用的是词法作用域,也就是静态作用域,就是在函数定义的时候,就已经确定了
var value=1
function foo(){
console.log(value)
}
function bar(){
var value=2;
foo()
}
bar() // 结果为 1
变量对象
变量对象是当前代码段中,所有的变量(变量 函数 形参 argumengts)组成的一个对象
变量对象时在执行上下文中被激活的,只有变量对象被激活了,在这段代码中才能使用所有的变量
变量对象分为全局变量对象(Variable Object VO)和局部变量对象(Active Object AO)
对于上面的代码,VO有(value,foo,bar),bar的AO有(value),foo的AO为空
闭包的底层原理
function a(){
var aa=123
console.log(aa)
return function b(){
console.log(aa)
}
}
var res=a()
res() // 输出123
按道理函数内部定义的变量,在函数外部是访问不到的,却成功打印出了函数内部的变量aa,这是因为:
由于b函数的定义依赖于a函数的执行,不执行a函数就不会有b函数的定义,所以b函数的定义和a函数的执行的作用域链是一样的:
a函数执行完后会断裂作用域链:
但是b也是走的和a一样的作用域链且b的作用域链没有被断裂:
b函数执行的时候先看到自己的AO,然后是a函数的AO,最后是外部的VO
所以b函数能访问a函数内部的变量,并且b函数是被return出去的,并没有被执行然后销毁,所以可以在函数外部调用b函数访问a函数内部的变量
闭包的应用场景
回调函数
防抖节流
定时器的传参
手写js特性 手写bind
笔试例题
function add(a) {
function s(b) {
if (b) {
a = a + b
}
return s
}
s.toString = function () {
return a
}
return s
}
console.log(add(1)(2)(3)(4)().toString())