闭包学习理解

闭包学习理解,第1张

闭包(closure) – 延伸了变量的作用域

闭包:一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。指有权访问另一个函数作用域中变量的函数。

闭包可以在一个内层函数中访问到其外层函数的作用域。延伸了变量的作用域

在JavaScript中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

示例1:

// 外层函数 -- 声明一个变量;return 一个内部函数
funciton fn() {
    var num = 0;
    // 内层函数
    return function() { // 调用外部函数 fn()的变量 num
        console.log(++num) // 延伸了num 作用域
    }
}
var fun = fn();
fun(); // 打印结果为 1
fun(); // 打印结果为 2

在本例子中,fun 是执行 fn 时创建的函数实例(return 的函数)的引用。该函数的实例维持了一个对它的词法环境(变量 num存在于其中)的引用。因此,当fun被调用时,变量num` 仍然可用,所以打印结果为 1

词法作用域

词法(lexical):指的是,词法作用域根据源代码中声明变量的位置来确定该变量在何处可用。

嵌套函数可访问声明于它们外部作用域的变量。

示例2:

function makeAdder(x) {
    return function(y) {
        return x + y;
    }
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 打印结果为 5
console.log(add10(2)); // 打印结果为 12

// 解析
add5 = makeAdder(5) = function(y) = 5+y
add5(2) = makeAdder(5) = function(2) = 5+2 = 7
add10 = makeAdder(10) = function(y) = 10+y
add10(2) = makeAdder(10) = function(2) = 10+2 = 12

add5 和 add10 都是闭包。它们共享相同的函数定义,但是保存了不同的词法环境。在 add5 的环境中,x为5。而在add10中,x则为10。

用闭包模拟私有方法 – 面试时可能会问道

私有方法的好处:

利于限制对代码的访问;提供了管理全局命名空间的强大能力;避免非核心的方法弄乱代码的公共接口部分。

在循环中创建闭包:一个常见错误 – 面试时可能会问道

在for循环中创建闭包时,可能会因为闭包共享一个词法作用域,造成错误。

解决方法:

为每个闭包创建单独的词法环境

使用匿名闭包

示例:

function showHelp(help) {
  document.getElementById('help').innerHTML = help;
}

function setupHelp() {
  var helpText = [
      {'id': 'email', 'help': 'Your e-mail address'},
      {'id': 'name', 'help': 'Your full name'},
      {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];

  for (var i = 0; i < helpText.length; i++) {
    (function() {
       var item = helpText[i];
       document.getElementById(item.id).onfocus = function() {
         showHelp(item.help);
       }
    })(); // 马上把当前循环项的item与事件回调相关联起来
  }
}

setupHelp();

使用关键词 let 而非 var (let 关键字有作用域;var 关键字无作用域)

可选方案 – 使用forEach()遍历数组

function showHelp(help) {
  document.getElementById('help').innerHTML = help;
}

function setupHelp() {
  var helpText = [
      {'id': 'email', 'help': 'Your e-mail address'},
      {'id': 'name', 'help': 'Your full name'},
      {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];

  helpText.forEach(function(text) {
    document.getElementById(text.id).onfocus = function() {
      showHelp(text.help);
    }
  });
}

setupHelp()

性能考量

闭包的缺点:闭包在处理速度和内存消耗方面对脚本性能具有负面影响。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1320343.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-11
下一篇2022-06-11

发表评论

登录后才能评论

评论列表(0条)

    保存