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 相关文章推荐
如何使用JS获取IE上传文件路径(IE7,8)
Jul 08 Javascript
Jquery 实现弹出层插件
Jan 28 Javascript
js实现Select下拉框具有输入功能的方法
Feb 06 Javascript
js HTML5 Ajax实现文件上传进度条功能
Feb 13 Javascript
jQuery实现的分页功能示例
Jan 22 Javascript
javascript简单链式调用案例分析
May 10 Javascript
React入门教程之Hello World以及环境搭建详解
Jul 11 Javascript
es7学习教程之fetch解决异步嵌套问题的方法示例
Jul 21 Javascript
纯js实现图片匀速淡入淡出效果
Aug 22 Javascript
vue.js实现带日期星期的数字时钟功能示例
Aug 28 Javascript
Bootstrap fileinput 上传新文件移除时触发服务器同步删除的配置
Oct 08 Javascript
详解Vue3使用axios的配置教程
Apr 29 Vue.js
零基础之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
Thinkphp事务操作实例(推荐)
2017/04/01 PHP
小议Function.apply() 之一------(函数的劫持与对象的复制)
2006/11/30 Javascript
js 自定义的联动下拉框
2010/02/07 Javascript
基于jquery的地址栏射击游戏代码
2011/03/10 Javascript
jquery调用asp.net 页面后台的实现代码
2011/04/27 Javascript
javascript两种function的定义介绍及区别说明
2013/05/02 Javascript
通过Jquery的Ajax方法读取将table转换为Json
2014/05/31 Javascript
JavaScript数组前面插入元素的方法
2015/04/06 Javascript
JavaScript实现将UPC转换成ISBN的方法
2015/05/26 Javascript
JS给Textarea文本框添加行号的方法
2015/08/20 Javascript
理解javascript中的严格模式
2016/02/01 Javascript
Bootstrap的fileinput插件实现多文件上传的方法
2016/09/05 Javascript
JavaScript省市区三级联动菜单效果
2016/09/21 Javascript
让html元素随浏览器的大小自适应垂直居中的实现方法
2016/10/12 Javascript
微信小程序之页面拦截器的示例代码
2017/09/07 Javascript
Angular实现点击按钮后在上方显示输入内容的方法
2017/12/27 Javascript
Vue-cli项目获取本地json文件数据的实例
2018/03/07 Javascript
新手简单了解vue
2019/05/29 Javascript
[50:34]VGJ.T vs Fnatic 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python学习笔记之常用函数及说明
2014/05/23 Python
Django数据库类库MySQLdb使用详解
2019/04/28 Python
使用NumPy读取MNIST数据的实现代码示例
2019/11/20 Python
Python xlrd模块导入过程及常用操作
2020/06/10 Python
opencv 形态学变换(开运算,闭运算,梯度运算)
2020/07/07 Python
一款CSS3实现多功能下拉菜单(带分享按)的教程
2014/11/05 HTML / CSS
Ever New美国:澳大利亚领先的女装时尚品牌
2019/11/28 全球购物
如何安装ruby on rails
2014/02/09 面试题
高校毕业生自我鉴定
2013/10/27 职场文书
幼儿教师研修感言
2014/02/12 职场文书
工地质量标语
2014/06/12 职场文书
实验室标语
2014/06/21 职场文书
KTV门卫岗位职责
2014/10/09 职场文书
2015年超市工作总结
2015/04/09 职场文书
100句人生哲理语录集锦:强者征服今天,懒汉坐等明天
2019/10/18 职场文书
Java9新特性之Module模块化编程示例演绎
2022/03/16 Java/Android
PYTHON InceptionV3模型的复现详解
2022/05/06 Python