博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
我理解的javascrpit闭包
阅读量:4086 次
发布时间:2019-05-25

本文共 2651 字,大约阅读时间需要 8 分钟。

名词解释

http://www.imooc.com/article/4509官方的解释可以无视了,比绕口令还要绕口令的拗口的词汇拼接。

个人理解就是在函数中嵌套函数。

前提

理解闭包必须先理解另外另个内容:1.作用域链 2.垃圾回收

作用域链

js中有两种变量,一种叫局部变量,一种叫全局变量。

没有写在function内部的都是全局变量,写在function内部的都是局部变量,为了避免自己定义的变量名污染全局变量名(尤其是现在调用的js控件越来越多的年代),因此很少会定义全局变量。

因为局部变量就是声明在function内部的变量,因此这个function就是该变量的作用域。也就是这个function内部,包括这个function的儿子(子函数)、孙子(子函数内的子函数),均可以访问到。这也就是说,这个function内部的子函数也可以访问到这个变量。

var f = function(){
// f就是a的作用域 var a = 999; function f1(){
// 因此,即使在f的内部嵌套函数(子函数)中也可以访问到a alert(a); } f1();};f();
垃圾回收机制

在函数执行的时候,js的解释器会给所有需要用到的变量分配一个内存空间,这样一直到这个函数执行结束,就会认为这些变量已经没有用了,就会启用垃圾回收机制来把这些内存回收。

这样在遇到函数嵌套时,如上面例子所示,在f执行完成之后,变量a因为还要被f1这个内部嵌套函数继续使用,因此a并不会被释放,因此,在f1()的结果是999

也就是说,在js解析器发现函数中嵌套了函数时,就会把函数中的变量和子函数中的变量一起保存在内存中,也就是构建了一个“闭包”。这些变量不会被内存回收器回收,只有当内部嵌套函数不再执行之后,才会被回收。

闭包案例
属性
var person = function(){
var name = "张三"; this.getName=function(){
return name; }; }; var p = new person(); alert(p.getName());

上面的代码里,name这个属性只能通过调用getName这个方法才能获取,这是必包的用法之一。

保存复杂计算中的临时变量

经典案例:

html:    
  • aaa
  • bbb
  • ccc
  • ddd

想要实现的效果是点击li的时候,alert各自的内容,

比如点击第一个,alert “aaa”
很多人第一反应的代码如下:

var foo = function(){
var lis = document.getElementsByTagName("li"); for (var i= 0;i

然后会发现结果和想象中完全不一样,点击任何一个都是返回4。

这是因为在赋值的时候,传的i是对内存地址对引用。当循环结束后,i指向对就是4.因此,所有的li在点击时都是alert(4)。

在这个时候就要用到闭包了。在每一次循环的时候,都把当前的i通过立即执行函数赋值。

如下所示:

用闭包实现Fibonacci数列

话不多说,直接上代码

var fibonacci = function(n){
// 将斐波那契数列放在这个临时变量中 var arr = [0,1,1]; var fi = function(m){
// 如果存在则直接返回 if(arr[m]){
return arr[m]; }else {
// 如果不存在则递归获取 arr[m] = fi(m-1)+fi(m-2); return arr[m]; } }; return fi(n); }; alert(fibonacci(10));

上面的代码如果不用闭包来做,那么arr数组将不能一直保存在内存中,每次递归都会重置了。

当然,以上代码可以进一步优化:

var fibonacci = (function(){
var arr = [0,1,1]; return function(n){
if(arr[n]){
return arr[n]; } else {
arr[n] = fibonacci(n-1)+fibonacci(n-2); return arr[n]; } }; })();

内部嵌套函数返回这样一个匿名函数:

function(n){
if(arr[n]){
return arr[n]; } else {
arr[n] = fibonacci(n-1)+fibonacci(n-2); return arr[n]; } }

因此主函数要立即执行才能返回结果。


作者: nickylau82 

链接:http://www.imooc.com/article/4509

来源:慕课网

转载地址:http://fkeni.baihongyu.com/

你可能感兴趣的文章
基于柯西矩阵的Erasure Code技术详解
查看>>
基于范德蒙矩阵的Erasure code技术详解
查看>>
一个IO的传奇一生(12)-- 磁盘阵列1
查看>>
主定理的证明及应用举例
查看>>
线性判别分析(Linear Discriminant Analysis,LDA) 简单分析
查看>>
leetcode刷题(五):分治算法
查看>>
【算法】动态规划算法—买卖股票的最佳时机系列(1-4)
查看>>
想从事分布式系统,计算,hadoop等方面,需要哪些基础,推荐哪些书籍?--转自知乎
查看>>
【经验总结】如何找方向相关(计算机)的论文
查看>>
计算机论文查找
查看>>
计算机方向学术入门经验
查看>>
大牛博士是如何进行文献检索和阅读(好习惯受益终生)
查看>>
【转】台湾教授-如何阅读科研论文
查看>>
《如何写好科研论文》
查看>>
最大长方形 (Maximum Submatrix & Largest Rectangle)(涵盖各种求最大矩形题目)
查看>>
强连通分量之Kosaraju算法
查看>>
动态规划法(六)鸡蛋掉落问题(一)
查看>>
LeetCode 887.鸡蛋掉落(C++)
查看>>
Dijkstra‘s algorithm (C++)
查看>>
奇异值分解(SVD)的原理详解及推导
查看>>