js学习(闭包本质,尾调用优化)
Posted lin_fightin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js学习(闭包本质,尾调用优化)相关的知识,希望对你有一定的参考价值。
在看书时想做的一些笔记
闭包本质
闭包通俗讲就是一函数对外部函数有引用变量,导致外部函数运行完毕后还不能被销毁,因为其内部变量还在被引用。
今天看书后发现有更深入的解释
以一个例子入手
如图,里面的匿名函数引用了外部函数create的变量propertyName,导致create函数在运行过后还不能被销毁。
js高级程序设计是这样说的
每个函数在调用的时候会产生一个执行上下文,如图
上下文中有一条作用域链,该链的最前端是函数内部的活动对象,如create的arguments,propertyName变量。然后一层一层往外找,直到全局上下文,全局变量对象为止,这就是作用域链。
而匿名函数的作用域链则是自己的活动对象,第二层则是create函数的活动对象,最外层才是函数的活动对象。
闭包解释
当函数执行完毕后,按道理来说,其作用域链会被销毁,内部的活动对象也会被销毁。但是上述函数执行后,craete函数运行完后,其作用域链会被销毁,但是其函数的活动对象并不会被销毁,因为此时匿名函数还在引用其函数活动对象中的变量,所以最后导致的结果应该是
红色部分的会被保存,只有当匿名函数也被销毁时,其作用域链,自身的活动对象,create的活动对象才会被销毁,剩下全局变量对象。
所以当存在很多闭包的时候,就会导致外部函数的活动对象不能被销毁,越积越多导致内存被过度占用,因此应该少用闭包。
es6尾调用优化
我们经常使用的递归,或者一个函数返回另一个函数调用的返回值,都属于尾调用,如图
函数在调用的时候会被推入栈,在es6尾调用优化前,应该是这样的
这是一个栈,当outer函数执行时会被推入,然后执行到Inner时,inner会被推入栈中,当树目一多容易产生很多桢栈,可能导致卡死。
而优化后的尾调用是这样的
当执行完outer后执行inner的时候,js引擎发现,弹出outer也没问题,因为inner的返回结果就是outer的返回结果,这样不管多少,都不造成桢栈过多的问题。
尾调用的优化条件
看一些不符合尾调用的例子
第一二个没有直接返回,第三个是过多的操作,违反执行额外的逻辑操作,第四个违反了第四点,闭包问题。
还有一些符合的例子
为什么要在严格模式呢?
因为f.arguments(参数)和f.caller(外部函数自身)会引用外部函数的桢栈。
以上是关于js学习(闭包本质,尾调用优化)的主要内容,如果未能解决你的问题,请参考以下文章