JavaScript返回函数怎么理解

案例分析

function main() {
  var name = 'xiaoming';
  return function () {
    console.log(name);
  }
}

var output = main();
output();

main()函数执行会返回一个函数,并赋值给了output。这说明output的定义时再main()外部,但为啥我在main()外部执行output()却可以使用name并正常输出name的值呢?

理解

上面的函数等同于下面这些代码

var output;
function main() {
    var name = 'xiaoming';
    output = function(){
        console.log(name);
    };
}
main();
output();

这样似乎好理解些了。

output在main函数之外,声明的是个全局变量。

但赋值其实是在main函数内部赋值的。

output指向的是main函数内部的那个函数。

这个函数的作用域是在main函数之内。

而name也是在main函数内定义的。且对于output指向的函数而言,name还是其全局变量呢。

这样看来,可以正常使用name也不足为怪了吧。

由此可见,变量output的作用域是全局的,但是并不会影响其指向的函数的作用域。

回到原来的案例:

  1. main函数返回的那个函数,其作用域是在main函数内部,即使赋值给了output变量,依然不会改变函数本身的作用域。

  2. name相对于那个函数是个全局变量,所以可以正常使用。

闭包引入

上述例子,其实是个闭包。所谓闭包:
是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境。
环境由闭包创建时在作用域中的任何局部变量组成。

闭包就是函数及声明函数时的词法环境。这个“环境”包含了创建闭包时,所有在作用域中的(in-scope)的局部变量。

在js中函数的变量作用域是通过作用域链定义的,它在函数定义的时候就已经创建了,而不是在调用函数时决定的。由于闭包的特性,当函数定义了嵌套的函数,并将它作为返回值返回或者存储在某处的属性里时,就会有一个外部引用指向这个嵌套的函数,同时将它的作用域链保存下来,而这条作用域链就包含了嵌套函数的局部变量以及定义他们的外部函数的局部变量。

本例中,执行main()并将嵌套函数返回给output时,output()生成的变量作用域链里,就包含了main()里的name及值。所以,可以正常输出name的值。

闭包的特点就是能把原始作用域的内容带出去(事实上是同作用域下的变量可以访问),
这里要重点记住一个特点:如果在某个作用域下但凡还有一个变量(包括函数变量)还在使用,那么这个作用域下的所有其他变量都不会销毁。

    原文作者:_我和你一样
    原文地址: https://www.jianshu.com/p/948c0b3d1e9e
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞