美文网首页
javascript闭包的形成图解

javascript闭包的形成图解

作者: hans_431c | 来源:发表于2019-03-30 23:32 被阅读0次

下面就来说说闭包的一些基本概念和具体的形成过程。

什么是闭包?

闭包就是既能重用一个变量,又可以保护变量不被污染的一种机制 。下面就通过一个小例子来帮助大家理解闭包的作用。

var i=1;
function add(){
 console.log(i++);
}
add() //1
add() //2
i=1;
add() // 1
add() // 2

假如上面的程序是用来取号排队乘地铁的,由于程序小哥哥的粗心大意,在中间某个地方给全局的变量i重新赋值,导致最后的取号重复啦,这是会导致非常不友好的后果的,估计广州的3号线天天得有人干架!(这就是上面所说的变量受到污染)。
导致上面变量污染的最基本原因就是i是一个全局变量,那么如果把i变成了函数内部的局部变量,又会出现什么样的情况呢?

function add(){
 var i=1;
 console.log(i++);
}
add() //1
add() //1
i=2;
add() // 1
add() // 1

上面这种情况也很好理解,因为每次调用完add()后,add自己的函数作用域AO就会被释放,所以每次得到的结果都为1,这种情况估计地铁里面的工作人员都要被****。很明显,这是因为i为函数内容自己的局部变量,既不能重用的原因。所以,闭包就是为了解决上面这种问题的(重用一个变量,又可以保护变量不被污染);

闭包的书写步骤:

1.用外层函数包裹住受保护的变量和内层函数
2.外层函数将内层函数返回到外部
3.使用者调用外层函数获得返回的内层函数对象

function() outer{
  var i=1;
  return function(){
  console.log(i++);
}
}
vat getNum=outer();
getNum();//1
getNum();//2
i=1;
getNum();//3
getNum();//4

由上面例子可以看出,变量i既能重用,又不会被污染。那到底闭包底层的原理是什么呢?说得概括一点就是,外层函outer的作用域AO无法释放。可能这句话大家看得很懵逼,下面就通过图解的方式,帮助大家简单明了地理解闭包的底层原理。
1.首先程序在刚开始执行之前,会创建ECS执行环境栈,用来存放一些变量或函数。


image.png

2.程序开始执行的时候,首先创建一个outer函数,和全局的getNum变量,所以此时window中会存放入outer和getNum


image.png
3.当outer函数被调用的时候,outer会放到ECS执行环境栈中,并且创建一个outer的执行环境AO,当执行到

var i=1这句代码的时候,outer的AO中就有了自己的局部变量i,


image.png

4.继续往下执行到return function() {console.log(i++);} 的时候,引擎就会创建一个函数,此时这个函数的祖籍为outer,不再是window,然后outer会把这个函数的地址返回给getNum,也就是说,这时候的getNum引用的就是outer内部return出来的小函数,而内部函数的祖籍又是outer,outer的parent又是window,此时就形成了一种相互抱团的情况。


image.png
图片中绿色的箭头,就是相互之间作用域链关系。
5.当outer调用完以后,outer会从ECS中释放,正常来说,outer的AO也会被跟着释放,但是请注意,这时候outer的AO 被内部的函数牵引着,因为内部函数的scope指向outer的AO,这就好比你手机上的微信一样,只要你还用得着,就不会把它卸载掉一样。也许你会问啦,那内部的function不会被释放吗?因为outer把内部的函数给return出来啦,所以此时的内部函数又被gerNum牵引着,故内部函数也释放不了,闭包就此形成。
image.png

6.当执行getNum()的时候,getNum就会被存放到ECS中,并且创造getNum的AO,但是因为getNum没有自己的局部变量i,当函数内部执行到console.log(i++)的时候,他就会沿着作用域链,往他的父集outer的AO中去寻找变量i,输出后并且执行i++,outer中的i就变了2


image.png
7.当执行到 i=1的时候,因为全局window中没有变量i,程序就会自动在全局中声明一个全局变量i,并且其值为1,此时并不会去操作outer函数AO中的局部变量i,所以outer执行环境中的变量i并不会受到污染。
以上就是对闭包的概念和形成原理的一些解释,希望可以帮助到一些需要的码友们。

相关文章

  • javascript闭包的形成图解

    下面就来说说闭包的一些基本概念和具体的形成过程。 什么是闭包? 闭包就是既能重用一个变量,又可以保护变量不被污染的...

  • js闭包问题

    javascript 闭包的概念,闭包的作用,闭包经典面试题详解(配图解) 函数作用域(闭包前置知识) 要彻底弄懂...

  • JS学习理解之闭包和高阶函数

    一、闭包 对于 JavaScript 程序员来说,闭包(closure)是一个难懂又必须征服的概念。闭包的形成与变...

  • 闭包(closure)

    闭包是函数和声明该函数的词法环境的组合。MDN MDN上的栗子 JavaScript中的函数会形成闭包。 闭包是由...

  • JavaScript----闭包

    javascript之闭包 闭包的概念     闭包(closure)是 JavaScript 的一种语法特性。 ...

  • 学习JavaScript闭包和作用域笔记

    JS JavaScript闭包和作用域 闭包 JavaScript高级程序设计中对闭包的定义:闭包是指有权访问另外...

  • 闭包--生存周期,实现命令模式,内存管理

    对于JavaScript程序员来说,闭包(closure)是一个难懂又必须征服的概念。闭包的形成与变量的作用域以及...

  • JavaScript之闭包

    什么是闭包? 简言之,闭包是函数引用其周边状态(词法环境)绑在一起形成的(封装)组合结构。在JavaScript中...

  • javascript中闭包是什么

    javascript中闭包是什么 JavaScript 变量可以是局部变量或全局变量。私有变量可以用到闭包。闭包就...

  • Javascript 闭包

    闭包 (注:所以案例以 javascript 实现) 初识闭包 什么是闭包 MDNClosures are fun...

网友评论

      本文标题:javascript闭包的形成图解

      本文链接:https://www.haomeiwen.com/subject/samsbqtx.html