[[2022-08-08]]
函数是一等公民
函数可以作为参数传递,也可以作为返回值(很灵活)
function foo(aaaaa) {
aaaaa()
}
function bar() {
console.log("bar")
}
foo(bar)
学过前两节后这个例子一下就理解了,这里就是把函数的引用地址当作参数传递过去了
函数作为返回值:
function foo (){
function bar () {
console.log("bar")
}
return bar //注意不要带(),带的话会执行一次再返回
}
var fn = foo() //带()就是执行一下得到bar地址再赋值,不带括号就是直接给foo函数的地址了
fn()
这个想了想才理解
function makeAdder(count) {
function add (num) {
return count + num
}
return add
}
var add5 = makeAdder(5) //这里带括号了,相当于执行了一下makeAdder(5),结果是add函数地址,所以add5就是add函数,count已经确定死是5了,就是add5在内层
console.log(add5(2))//所以这里就是相当于给内层的add的num传入2
42行的var add5 = makeAdder(5)这里函数已经调用完了,count应该销毁,但是这里没有销毁,就是因为存在闭包
高阶函数
有个函数,如果这个函数接收其他函数作为参数,或者自己返回另一个函数作为返回值,那这个就是高阶函数。
js中常用的高阶函数
[[2022-08-08]]16:25,暂停
[[2022-08-09]]12:10,继续
数组的filter方法

在filter里面传个函数,自己写的判断函数,必须返回true或false,用来给filter判断当前元素要不要放入过滤后的新数组
数组里有几个元素,filter就执行几次你给的函数。
map函数
forEach
find/findIndex
reduce -累加
nums.reduce( function (preValue, item) { //preValue是上一次返回的结果
return preValue + item
} , initalValue) //这里有一个初始化的值
闭包
定义
emm,确实不好理解
[[2022-08-09]]今天看到了第三集1小时30分处
[[2022-08-10]] 开搞开搞,现在看个2.5h

上面讲的这个函数👇
function foo() {
var name = "foo"
function bar () {
console.log("bar", name)
}
return bar
}
var fn = foo()
fn()
这里的bar和name引用就组成了闭包
执行完
var fn = foo()以后,foo的栈内存里的函数执行上下文会删掉,堆内存里的AO按理来说应该也删掉,但是这时他没删,后来的fn仍然能访问foo的AO里的name,这时bar函数和它带的name引用就组成了闭包i
闭包和函数的最大区别在于,当捕捉闭包的时候,它的自由变量也会被确定,这样即使脱离了捕捉时的上下文,它也能照常运行。
总结
一个最基本的普通函数(里头是空的)算不算闭包?
广义来说(可以访问):JavaScript中所有函数都是闭包
狭义来说(有访问到):如果JavaScript函数有访问外层作用域的变量,是闭包
内存
函数执行过程的内存
var message = "hello"
function foo (){
var name = "foo"
var age = 18
function bar() {
console.log("name")
console.log("age")
}
return bar
}
var fn = foo()
fn()

为什么foo执行完以后不会销毁AO呢?
因为里面的bar被返回给了全局的fn变量,这时候可以从根(全局变量)出发一直引用到AO那里,就不会被销毁(看前面的GC垃圾回收那里的标记清除法)
闭包的内存泄漏
像上面这种情况,从根部开始有引用指着,那GC就不能回收它了。同时如果只需要用到一次的话,那用完这一次以后他也不能被GC回收,这时候就叫做内存泄漏(虽然我也不知道为啥叫作“泄漏”,感觉不够直观,我觉得应该是存在未清理的垃圾的意思才对)
怎么解决呢?直接去掉引用就可以了,fn = null
如果后续还要继续用的话,那就不算是内存泄漏了,泄不泄漏主要看后面还用不用。