【 js 基础 】【读书笔记】作用域和闭包
var a = 2;

步骤三:代码生成
将 抽象语法树 (AST)转换为可执行代码。
然而对于解释型语言(例如JavaScript)来说,通过词法分析和语法分析得到语法树,没有生成可执行文件的这一过程,就可以开始解释执行了。
对于 var a = 2; 进行处理的时候,会有 引擎、编译器、还有作用域的参与。
引擎:从头到尾负责整个 Javascript 程序的编译及执行过程。
编译器:负责语法分析及代码生成等。
作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符(变量)的访问权限。
他们是这样合作的:
首先编译器会进行如下处理:
1、var a,编译器会从作用域中寻找是否已经有一个该名称的变量存在于同一个作用域的集合中。如果是,编译器会自动忽略该声明,继续进行编译;否则它会要求作用域在当前作用域的集合中声明一个新的变量,并命名为 a 。
2、接下来编译器会为引擎生成运行时所需的代码,这些代码用来处理 a = 2 这个赋值操作。引擎运行时会首先从作用域中查找 当前作用域集合中是否存在 变量 a。如果有,引擎就会使用这个变量。如果没有,引擎就会继续向上一级作用域集合中查找改变量。
然后 如果引擎最终找到了 变量 a,就赋值 2 给它。如果没有找到,就会抛出一个异常。
总结:
变量的赋值操作分两步完成:第一步 由编译器在作用域中声明一个变量(前提是之前没有声明过),第二步 是在运行时引擎会在作用域中查找该变量,如果可以找到,就对其赋值。
二、作用域
1、RL 查询
在上一部分我们说到了,引擎会对变量 a 进行查找。而查找分为两种,一是 LHS(Left-Hand-Side) 查询,二是 RHS(Right-Hand-Side) 查询。
LHS 查询:试图找到变量的容器本身,从而可以对其赋值。也就是查找 变量 a 。
RHS 查询:查找某个变量的值。查找变量 a 的值,即 2。
例子:
console.log(a); // 这里对 a 是一个 RHS 查询,找到 a 的值,并 console.log 出来。
a = 2; // 这里对 a 是一个 LHS 查询,找到 变量 a,并对其赋值为 2 。
function foo(a){
console.log(a); //
} foo(2); // 这里首先对 foo() 函数调用,执行 RHS 查询,即找到 foo 函数,然后 执行了 a = 2 的传参赋值,这里首先执行 LHS 查询 找到 a 并赋值为 2,然后 console.log(a) 执行了 RHS 查询。
function foo(a){
var b = a*2;
function bar(c){
console.log(a,b,c);
} bar(b*3);
}
foo(2); // 2,4,12
在这段代码中有三层作用域,如图所示嵌套:
window.a
foo(); function foo(){
console.log(a);
var a = 2;
}
学了上面的知识,你应该可以猜到 foo() 可以正常执行,而 console.log(a) 会打出 undefined; 原因是当把提升应用到上面代码,代码就相当于 下面的形式:
function foo() {
var a;
console.log(a);
a = 2;
} foo();
function foo() {
var a;
console.log(a);
a = 2;
}
函数表达式:
var foo = function() {
var a;
console.log(a);
a = 2;
} (function foo(){
var a;
console.log(a);
a = 2;
})();
那么对于提升,来看个例子:
foo(); // 报TypeError错误 var foo = function() {
var a;
console.log(a);
a = 2;
}
这段代码相当于
var foo;
foo(); // 此时 foo 为 undefined,而我们尝试对它进行函数式调用,属于不合理操作,报 TypeError 错误。
foo = function() {
var a;
console.log(a);
a = 2;
}
foo(); // 1
var foo;
function foo(){
console.log(1);
}
foo = function(){
console.log(2);
}
会输出 1 为不是 2,这段代码提升之后相当于:
function foo(){
console.log(1);
}
foo();
foo = function(){
console.log(2);
}
foo(); // function foo(){
console.log(1);
}
var foo = function(){
console.log(2)
} function foo(){
console.log(3)
}
function foo(){
var a = 2;
function bar(){
console.log(a);
}
return bar;
} var baz = foo();
baz(); //
function wait(message){
setTimeout(function timer(){
console.log(message)
},1000)
} wait("hi");
function foo(){
var a = 2;
function baz(){
console.log(a); //
}
bar(baz);
} function bar(fn){
fn(); //闭包
}
for (var i=0;i<=5;i++){
setTimeout(function timer(){
console.log(i)
},i*1000)
}
for (var i=0;i<=5;i++){
(function(i){
setTimeout(function timer(){
console.log(i)
},i*1000)
})(i)
}

【 js 基础 】【读书笔记】作用域和闭包的更多相关文章
- JS基础知识笔记
2020-04-15 JS基础知识笔记 // new Boolean()传入的值与if判断一样 var test=new Boolean(); console.log(test); // false ...
- JS基础篇之作用域、执行上下文、this、闭包
前言:JS 的作用域.执行上下文.this.闭包是老生常谈的话题,也是新手比较懵懂的知识点.当然即便你作为老手,也未必真的能理解透彻这些概念. 一.作用域和执行上下文 作用域: js中的作用域是词法作 ...
- 【js】【读书笔记】廖雪峰的js教程读书笔记
最近在看廖雪峰的js教程,重温了下js基础,记下一些笔记,好记性不如烂笔头嘛 编写代码尽量使用严格模式 use strict JavaScript引擎是一个事件驱动的执行引擎,代码总是以单线程执行 执 ...
- handlebars.js基础学习笔记
最近在帮学校做个课程网站,就有人推荐用jquery+ajax+handlebars做网站前端,刚接触发现挺高大上的,于是就把一些基础学习笔记记录下来啦. 1.引用文件: jquery.js文件下载:h ...
- JS三座大山再学习 ---- 作用域和闭包
本文已发布在西瓜君的个人博客,原文传送门 作用域 JS中有两种作用域:全局作用域|局部作用域 栗子1 console.log(name); //undefined var name = '波妞'; v ...
- 我不知道的js(一)作用域与闭包
作用域与闭包 作用域 什么是作用域 作用域就是一套规则,它负责解决(1)将变量存在哪儿?(2)如何找到变量?的问题 作用域工作的前提 谁赋予了作用域的权利?--js引擎 传统编译语言编译的过程 分词/ ...
- JS基础知识(作用域/垃圾管理)
1.js没有块级作用域 if (true) { var color = “blue”; } alert(color); //”blue” for (var i=0; i < 10; i++){ ...
- 说说循环与闭包——《你不知道的JS》读书笔记(一)
什么是闭包 <你不知道的JS>里有对闭包的定义:"当函数可以记住并访问所在的词法作用域,即使函数是在当前作用域之外执行,这就产生了闭包." 讲闭包是啥的太多了...就一 ...
- js高程读书笔记(第4章--变量、作用域和内存)
JavaScript变量松散类型的本质,决定了它只是在特定时间用于保存特定值的一个名字而已.由于不存在定义某个变量必须要保存何总数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变. 1. ...
- 两万字Vue.js基础学习笔记
Vue.js学习笔记 目录 Vue.js学习笔记 ES6语法 1.不一样的变量声明:const和let 2.模板字符串 3.箭头函数(Arrow Functions) 4. 函数的参数默认值 5.Sp ...
随机推荐
- AjaxResult
package com.sprucetec.tms.utils; /** * AjaxReturn * * @author Yinqiang Du * @date 2016/7/12 */import ...
- Python大法之告别脚本小子系列—各类URL采集器编写
本文作者:i春秋签约作家——阿甫哥哥 系列文章专辑:https://bbs.ichunqiu.com/forum.php?mod=collection&action=view&ctid ...
- Android动画Animation简单示例
Animation是Android给我们提供的一个可以实现动画效果的API,利用Animation我们可以实现一系列的动画效果,比如缩放动画,透明度动画,旋转动画,位移动画,布局动画,帧动画等等.An ...
- NVIDIA GRID 和 NICE DCV 技术用于实现 Linux 和 Windows® 图形加速虚拟桌面
NVIDIA GRID 和 NICE DCV 技术用于实现 Linux 和 Windows® 图形加速虚拟桌面. NICE DCV: 满足 LINUX 和 WINDOWS 的远程 3D 通过 NICE ...
- 10-02 Java 形式参数和返回值的问题深入研究,链式编程
形式参数和返回值的问题: 1:形式参数和返回值的问题(理解) (1)形式参数: 类名:需要该类的对象 抽象类名:需要该类的子类对象 接口名:需要该接口的实现类对象 (2)返回值类型: 类名:返回的是该 ...
- CDH 版本子节点启动问题
今天下午整整为了启动一个节点瞎忙活一下午,惨痛的教训还是记录下来吧,毕竟付出了代价.事情原委,一个同事在一台机器上占用了大量内存训练CTR点击率模型,而这台机器上部署了分布式Hadoop的一个data ...
- sql server always on安装
always on 是sql server 服务器的数据同步备份容灾工具, 集中了故障转移群集.数据库镜像和日志传送等功能. 环境: window server 2012 sql server 201 ...
- mybatis 关联映射
一对一 创建数据表 CREATE TABLE `tb_card` ( `id` int NOT NULL AUTO_INCREMENT , `code` varchar() NULL , PRIMAR ...
- MySql中插入乱码问题解决
今天在使用Java写入数据库时候,发现Insert语句和Update语句在执行过后,数据库中中文显示的是“??”,经过一番查阅,其中关键的问题在于编码格式是否统一. 其中创建表时候,每个关键字的格式都 ...
- Centos7下安装redis实战(单机版以及集群)
一.背景 因项目需要,要引入redis做缓存,就在centos7下亲自安装了一遍redis,刚好趁着这个机会就来把redis的概念以及单机版和集群版redis安装步骤记录下来,在此和大家一起分享. 二 ...