闭包,递归,

来源:互联网 发布:俄罗斯现状 知乎 编辑:程序博客网 时间:2024/06/04 22:12

递归:递归函数是在一个函数通过名字调用自身的情况下构成的。

匿名函数:function关键字后面没有函数名称标识符。(function(){...})()   //声明并立刻调用一个匿名函数

闭包:指有权访问另一个函数作用于中的变量的函数。在一个函数内部创建另一个函数,这时闭包就形成了。

执行环境有一个表示变量的对象:变量对象,

当一个函数被创建时,会创建一个预先包含全局变量对象的作用域链,它保存在[[Scope]]属性中。

当它被调用时,会创建一个执行环境,然后复制[[Scope]]构建执行环境的作用域链。然后使用自动取得的arguments和其他命名参数的值来初始化该函数的活动对象(变量对象),并被其推入执行环境作用域链的前端。

每个函数被调用时都会自动取得两个特殊变量:this和arguments

arguments:参数对象,指向对实参对象的引用,是类数组对象。有length属性,callee属性和caller属性。

callee:当前正在执行的函数(对象)

caller:调用当前正在执行函数(对象)的对象。

作用域链本质上是一个执行变量对象的指针列表,只引用但不实际包含变量对象。

作用域链只能向上访问。

一般,当一个函数执行完毕后,局部活动对象会被销毁。

但是闭包不同,闭包执行结束后,活动对象不会被销毁,因为内层函数(一般是匿名函数)的作用域链仍然在引用这个活动对象。

所以!!
闭包不能滥用,否则会导致内存泄露,影响网页的性能。闭包使用完了后,要立即释放资源,将引用变量指向null。

栗子:转自:https://segmentfault.com/a/1190000006669394

  • 当一个函数执行时,全局会为这个函数做两件事:1.构建一个独立的函数环境 2.把全局的变量用作用域链的形式推给这个函数,换句简单的话说就是让这个函数可以访问到它外层定义的变量,并可以一层一层的向外引用

  • 如果一个函数里面嵌套了一个函数,并且这个内部函数引用外层函数的变量,那个这个变量就不能在外层函数结束后被释放(正常是函数调用完,环境和变量就都会被释放),因为不知道内部函数在什么时候就会被调用。

// 需求时是一秒钟之后,在控制台依此输出1-10

function numberLog() {    for (var i = 1;i <= 10;i++) {        setTimeout(function () {            console.log(i)        }, 1000)    }}numberLog();

代码的执行速度很快,我们循环了十次,生成了十个setTimeout(function(){console.log(i)},1000)
然后当一秒钟过去了,i早就变成11了,所以最后就会输出10个11

改进后

function numberLog() {    for (var i = 1;i <= 10;i++) {        (function (count) {            setTimeout(function () {                return console.log(count)            }, 1000)        })(i)    }}numberLog();
那上面这个例子是怎么回事呢?
我们可以看到在循环代码内我们执行了一个函数立即调用,并且返回一个console.log(XX)
由于立即调用的这个函数引用了外部函数numberLog的变量i,因此i从1-10都不会被释放,都会在内部形成一个闭包空间。
当一秒钟过去,还是会打印出 1-10

原创粉丝点击