相关资料:

    • 闭包
    • 《JavaScript 高级程序设计》

    闭包是指有权访问另一个函数作用域中变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。

    1. function createComparisonFunction(propertyName) {
    2. return function(object1, object2) {
    3. var value1 = object1[propertyName];
    4. var value2 = object2[propertyName];
    5. if (value1 < value2) {
    6. return -1;
    7. } else if (value1 > value2) {
    8. return 1;
    9. } else {
    10. return 0;
    11. }
    12. };
    13. }

    一般来说,当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域(全局执行环境的变量对象),但是闭包的情况又有所不同。闭包会将包含函数(即外部函数)的活动对象添加到它的作用域中。当外部函数执行完毕之后,虽然外部函数的执行环境的作用域链被销毁,但是,由于闭包的作用域链仍然在引用外部函数的活动对象,因此外部函数的活动对象仍然会留在内存中,直至匿名函数被销毁。

    由于闭包保存的是整个变量对象,而不是某个特殊的变量,因此闭包只能获取包含函数中任何变量的最后一个值。

    1. function createFunctions (params) {
    2. var result = new Array()
    3. for (var i=0; i < 10; i++) {
    4. result[i] = function() {
    5. return i
    6. }
    7. }
    8. return result
    9. }
    10. const result = createFunctions()
    11. console.log(result[0]()); // 10

    在执行 result[0]() 的时候,会在作用域链中搜索 i 这个变量。由于此时 i 变量在外部函数活动对象中保存的值是 10,因此 result[0]() 的执行结果为 10。

    要想 result[0]() 的执行结果为 0,可以再创建一个匿名函数去包裹闭包。此时闭包中的 num ,则是每次循环中当前的 i 。

    1. function createFunctions (params) {
    2. var result = new Array()
    3. for (var i=0; i < 10; i++) {
    4. result[i] = function(num) {
    5. return function () {
    6. return num;
    7. };
    8. }(i);
    9. }
    10. return result
    11. }
    12. const result = createFunctions()
    13. console.log('result', result[0]()); // 0