JavaScript解析机制与闭包原理实例详解


Posted in Javascript onMarch 08, 2019

本文实例讲述了JavaScript解析机制与闭包原理。分享给大家供大家参考,具体如下:

js解析机制:

js代码解析之前会创建一个如下的词法环境对象(仓库):LexicalEnvironment{ }

在扫描js代码时会把:

1、用声明的方式创建的函数的名字;

2、用var定义的变量的名字存到这个词法环境中;

3、同名的时候:函数声明会覆盖变量,下面的函数声明会覆盖上面的同名函数;

4、函数的值为:对函数的一个引用; 变量的值为undefined;

5、如果用函数表达式的方式创建一个函数:

var fn = function(){ } 这样词法环境中存的是一个变量名fn,并赋值为undefined;

在调用函数的时候如果在函数上面调用就会出现和变量一样的情况报错undefined;

这也是以两种不同方式创建函数的区别;

LexicalEnvironment(这个词法环境===window)
{
fn: 对函数的一个引用;
b:undefined;
}

用声明的方式创建的函数:

function fn(){ };

用var定义的变量:

var b=5;

每次调用函数的时候就会创建一个新的词法环境对象(仓库):LexicalEnvironment{ };
在解析函数内部的变量和函数声明的时候跟全局词法环境相同,不过有两点需要注意,如下:

LexicalEnvironment(这个词法环境===fn)
{
a:对函数的一个引用;(解析的时候函数声明把变量覆盖了,尽管变量已经被赋值为1)
b:2;(解析的时候把变量存在了词法环境里,同时赋值为2)
}

 

function fn (a,b){
  alert(a)// function a(){ }
  alert(b)//2
  var b= 100;
  function a(){ }
}
fn(1,2);

调用函数并传递参数的时候,词法环境里会再存变量名的同时赋值,如果是函数内部有同名的函数声明则会把传入的参数覆盖;如果形参只有一个,那么另一个实参则被赋值为undefined;

闭包:

定义:(有多种定义)

1、(比较通俗的定义):函数嵌套函数,内部函数可以引用外部函数的参数和变量,这些参数和变量不会被垃圾回收机制所回收;

2、在计算机科学中,闭包是词法闭包的简称,是引用了自由变量的函数,这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外(意思就是不会被销毁)。

3、闭包是由函数和其相关的引用环境组合而成的实体。(潜台词就是这个函数将和引用环境同时存在,必须有引用)

综合来说,不管怎么定义都是在围绕着两个本质:函数在引用变量,这个变量将不会被销毁。

什么叫做被引用的自由变量离开了创造它的环境?如下:

function fn(){
  var a = 10;
  var b = 20;
  return function fn2(){
    alert(a);
  }
}
var result = fn();
result();//10;

以上代码就是fn2在被return出去以后,离开了fn函数这个环境,但是在外部调用依然能够访问到fn的变量;

这就是被引用的变量不会被销毁;同理在自执行函数这个闭包里,虽然自执行函数在自身执行过后内部变量本该被垃圾回收机制所回收,但是由于其内部有引用它的变量的子函数,也就是说构成了闭包,它的变量依然不会被销毁;

由此可见闭包的一个作用就是:我们能够通过闭包的方法来在外部访问到一个内部函数的变量;

很多人在解释闭包的时候都会把子函数return出去以后在外部调用,其实无论在哪里调用,闭包都已经形成了,只要是函数嵌套函数,并且子函数引用了父函数的变量,(不论子函数有没有被调用,这个用一种方法证明:在子函数内部打断点,在f12中观察闭包里的内容,已经出现了引用函数,这时候调用还没有被执行)这个时候闭包已经形成了。

闭包的本质:就是形成了作用域链。

注意:形成闭包的条件:1、函数要嵌套;2、子函数要引用父函数的变量(如果没有引用,则不会形成闭包,如果是引用父函数的父函数的变量也会形成闭包);

父函数每调用一次,就会形成一个新的闭包(函数每调用一次,就 会复制一份),也就是说形成一个新的词法作用域,重新引用父函数的变量;

以下代码说明:

function fn() {
  var num = 1;
  return function() {
    num++;
    alert(num);
  }
}
var result1 = fn();
result1();//2;
result1();//3;
var result2 = fn();
result2();//2;
result2();//3;

在fn被调用两次时,都形成了新的闭包,有各自新的词法作用域,所以result2的输出结果不受result1的影响;

函数每调用一次,都会复制一份新的,可以说明for循环里i的问题;

for (var i = 0; i < 5; i++) {
  (function(index){
    oDiv.onclick = function() {
      alert(index)
    }
  })(i)
}

自执行函数每调用一次都会复制一份新的,传进的i值也在变化,由于在函数静态作用域里,在预解析阶段已经确定了变量的作用域,所以子函数引用的父函数变量index只能是每次复制的那个父函数变量,所以就实现了我们想要取不同的i值的目的;

闭包的用途:

1、匿名自执行函数

不污染全局变量,(否则被声明为全局变量的话别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。提高效率;

2、结果缓存:

我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间利用闭包,它不会释放外部的引用,从而函数内部的值可以得以保留。,这样我们在第二次调用的时候,就会从缓存中读取到该资源。

3、实现封装;

4、实现类和继承(构造函数);

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
妙用Jquery的val()方法
Jun 27 Javascript
解决jquery1.9不支持browser对象的问题
Nov 13 Javascript
一个JavaScript获取元素当前高度的实例
Oct 29 Javascript
jQuery中$.click()无效问题分析
Jan 29 Javascript
javascript运动详解
Jul 06 Javascript
javascript中JSON.parse()与eval()解析json的区别
May 19 Javascript
AngularJS使用带属性值的ng-app指令实现自定义模块自动加载的方法
Jan 04 Javascript
jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解
May 01 jQuery
vue2.0 路由模式mode=&quot;history&quot;的作用
Oct 18 Javascript
利用原生JS实现欢乐水果机小游戏
Apr 23 Javascript
iview实现图片上传功能
Jun 29 Javascript
微信小程序实现页面左右滑动
Nov 16 Javascript
零基础之Node.js搭建API服务器的详解
Mar 08 #Javascript
详解vue项目中使用token的身份验证的简单实践
Mar 08 #Javascript
Javascript之高级数组API的使用实例
Mar 08 #Javascript
详解基于vue-cli3快速发布一个fullpage组件
Mar 08 #Javascript
JavaScript实现预览本地上传图片功能完整示例
Mar 08 #Javascript
详解JavaScript 的变量
Mar 08 #Javascript
Angular使用ControlValueAccessor创建自定义表单控件
Mar 08 #Javascript
You might like
PHP中读取文件的几个方法总结(推荐)
2016/06/03 PHP
PHP实现RTX发送消息提醒的实例代码
2017/01/03 PHP
php post换行的方法
2020/02/03 PHP
用函数式编程技术编写优美的 JavaScript
2006/11/25 Javascript
jQuery使用动态渲染表单功能完成ajax文件下载
2013/01/15 Javascript
JS验证邮箱格式是否正确的代码
2013/12/05 Javascript
js简单的弹出框有关闭按钮
2014/05/05 Javascript
JavaScript实现带缓冲效果的随屏滚动漂浮广告代码
2015/11/06 Javascript
基于JavaScript实现手机短信按钮倒计时(超简单)
2015/12/30 Javascript
js实现控制textarea输入字符串的个数,鼠标按下抬起判断输入字符数
2016/10/25 Javascript
使用base64对图片的二进制进行编码并用ajax进行显示
2017/01/03 Javascript
ES6中字符串string常用的新增方法小结
2017/11/07 Javascript
详解微信小程序审核不通过的解决方法
2018/01/17 Javascript
Angular HMR(热模块替换)功能实现方法
2018/04/04 Javascript
Vue中Axios从远程/后台读取数据
2019/01/21 Javascript
Node.js+Express+Mysql 实现增删改查
2019/04/03 Javascript
jquery中为什么能用$操作
2019/06/18 jQuery
微信内置浏览器图片查看器的代码实例
2019/10/08 Javascript
Vue实现todo应用的示例
2021/02/20 Vue.js
[04:37]DOTA2英雄梦之声Vol20发条
2014/06/20 DOTA
python中使用pyhook实现键盘监控的例子
2014/07/18 Python
Python中str is not callable问题详解及解决办法
2017/02/10 Python
python+requests+unittest API接口测试实例(详解)
2017/06/10 Python
分享给Python新手们的几道简单练习题
2017/09/21 Python
python使用Plotly绘图工具绘制水平条形图
2020/03/25 Python
将python依赖包打包成window下可执行文件bat方式
2019/12/26 Python
基于python实现破解滑动验证码过程解析
2020/05/28 Python
详解BeautifulSoup获取特定标签下内容的方法
2020/12/07 Python
纯CSS打造(无图像无js)的非常流行的讲话(语音)气泡效果
2012/12/28 HTML / CSS
方太官方网上商城:销售方太抽油烟机、燃气灶、消毒柜等
2017/01/17 全球购物
马来西亚户外装备商店:PTT Outdoor
2019/07/13 全球购物
时尚孕妇装:HATCH Collection
2019/09/24 全球购物
现代绅士日常奢侈品:Todd Snyder
2019/12/13 全球购物
新娘父亲婚礼致辞
2014/01/16 职场文书
绿色出行口号
2014/06/18 职场文书
详细谈谈MYSQL中的COLLATE是什么
2021/06/11 MySQL