你不知道的JavaScript(上)作用域与闭包
第一部分 作用域与闭包
第一章 作用域是什么
1、作用域
变量赋值操作会执行两个动作:首先编译器会在当前作用域中声明一个变量(如果之前没有声明过),
然后会在运行时引擎会在作用域中查找该变量,找到就会对他赋值。
2、理解LHS和RHS操作赋值
简单来说 LHS:查找的目的是进行变量赋值,使用LHS查询【存】
RHS:目的是获取变量的值,就会用RHS【取】
3、JavaScript编译原理 例如var a=2会被拆分为 var a在其作用域中声名新变量;a = 2会查询变量a并且对它赋值
4、不成功的RHS会抛出ReferenceError异常。不成功的LHS引用会导致自动隐式地创建一个全局变量(非严格模式下),该变量使用LHS引用的目标未标识符,或者抛出ReferenceError异常(在严格模式下)
第二章 词法作用域
词法作用域意味着作用域由书写代码时函数声明的位置来决定的,JavaScript有两个机制可以“欺骗词法作用域”:eval(...)和with.
1、eval()可以对一段包含一个或多个声明的“代码”字符串进行演算,借此修改已经存在的词法作用域(在运行时)
2、with本质上是通过将一个对象的引用当作作用域来处理,将对象的属性当作左通谕德标识符来处理,
从而创建一个新的词法作用域(同样在运行时)
不推荐使用,因为由副作用:
都会使引擎无法在编译时对作用于查找进行优化,,都会导致代码运行变慢【不要使用它们】
第三章 函数作用域与块作用域
函数作用域的含义时指,属于这个函数的全部变量都可以在整个函数的范围内使用及复用(事实上在嵌套的作用域中也可以使用)
隐藏内部实现
“隐藏”变量和函数是一个有用的技术。原因:
1、最小授权或最小暴露原则,这个原则是指在软件设计中,应该最小限度地暴露必要内容,而将其他内容都“隐藏”起来
2、可以规避同名标识符之间的冲突
如何解决?
方法一:全局命名空间
在全局作用域中声明一个足够独特的变量,通常是一个对象。这个对象被用作库的命名空间,所有需要暴露在外界的功能都会
成为这个对象的属性,而不是将自己的标志符暴露在顶级的词法作用域中
例如
var MyAnimals = {
style:"comfortable",
eatingSomething:function(){ },
doSomething:function(){ }
};
方法二 模块化的管理
3、函数作用域
var a = 2;
(function foo(){
var a = 3;
console.log(a);//3
})(); console.log(a);//2
区分函数声明和函数表达式最简单的方法是看function关键字出现在声明中的位置(不仅仅是一行代码,而是整个声明中的位置),如果function是声明中的第一个词,那么就是函数声明,否则就是函数表达式。
4、匿名与具名 :函数表达式可以使匿名的,但是函数声明不可以省略函数名
5、立即执行函数表达式
var a = 2;
(function foo() {
var a = 3;
console.log( a ); //
})();
console.log( a ); //
6、块作用域
(1)with 用 with 从对象中创建出的作用域仅在 with 声明中而非外部作用域中有效
(2) try/catch try / catch 的 catch 分句会创建一个块作用域,其中声明的变量仅在 catch 内部有效
例子
try {
undefined(); // 执行一个非法操作来强制制造一个异常
}
catch (err) {
console.log( err ); // 能够正常执行!
}
console.log( err ); // ReferenceError: err not found
(3)ES6引入的新关键字let。let关键字可以将变量绑定到所在的任意作用域中(通常是 { .. } 内部)。也就是说,let为其声明的变量隐式地在所在的块作用域。
隐式的块
var foo = true;
if (foo) {
let bar = foo * 2;
bar = something( bar );
console.log( bar );
}
console.log( bar ); // ReferenceError
显式的快 只要声明是有效的,在声明中的任意位置都可以使用 { .. } 括号来为 let 创建一个用于绑定的块
var foo = true;
if (foo) {
{ // <-- 显式的快
let bar = foo * 2;
bar = something( bar );
console.log( bar );
}
}
console.log( bar ); // ReferenceError
注意:使用 let 进行的声明不会在块作用域中进行提升。声明的代码被运行之前,声明并不“存在”的
第四章 提升
(1)正确的思考思路是,包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理。
(2)只有声明本身会被提升,而赋值或其他运行逻辑会留在原地
(3)函数优先 函数声明和变量声明都会被提升。但是一个值得注意的细节(这个细节可以出现在有多个“重复”声明的代码中)是函数会首先被提升,然后才是变量。
第五章 作用域闭包
闭包也就是函数嵌套函数
作用:1、作为返回值【定时器与闭包】
2、作为参数传递
模块模式两个必备条件:
1、必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块实例)
2、封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态。
ES6中引入模块
1、import可以将一个模块中的一个或多个API导入到当前作用域中,并分别绑定在一个变量上
2、module会将整个模块的API导入并绑定到一个变量上
3、export会将当前模块的一个标识符(变量、函数)导出为公共 API
例子:
bar.js
function hello(who) {
return "Let me introduce: " + who;
}
export hello; foo.js
// 仅从 "bar" 模块导入 hello()
import hello from "bar";
var hungry = "hippo";
function awesome() {
console.log(
hello( hungry ).toUpperCase()
);
}
export awesome; baz.js
// 导入完整的 "foo" 和 "bar" 模块
module foo from "foo";
module bar from "bar";
console.log(
bar.hello( "rhino" )
); // Let me introduce: rhino
foo.awesome(); // LET ME INTRODUCE: HIPPO
你不知道的JavaScript(上)作用域与闭包的更多相关文章
- 你不知道的JavaScript(作用域和闭包)
作用域和闭包 ・作用域 引擎:从头到尾负责整个JavaScript的编译及执行过程. 编译器:负责语法分析及代码生成等. 作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非 ...
- 我认知的javascript之作用域和闭包
说到javascript,就不得不说javascript的作用域和闭包:当然,还是那句老话,javascript在网上都说得很透彻了,我也就不过多的强调了: 作用域:javascript并没有像其他的 ...
- 读书笔记-你不知道的JavaScript(上)
本文首发在我的个人博客:http://muyunyun.cn/ <你不知道的JavaScript>系列丛书给出了很多颠覆以往对JavaScript认知的点, 读完上卷,受益匪浅,于是对其精 ...
- 你不知道的JS之作用域和闭包 附录
原文:你不知道的js系列 A 动态作用域 动态作用域 是和 JavaScript中的词法作用域 对立的概念. 动态作用域和 JavaScript 中的另外一个机制 (this)很相似. 词法作用域是 ...
- 你不知道的JS之作用域和闭包(五)作用域闭包
原文:你不知道的js系列 一个简单粗暴的定义 闭包就是即使一个函数在它所在的词法作用域外部被执行,这个函数依然可以访问这个作用域. 比如: function foo() { var a = 2; fu ...
- javascript的作用域和闭包(三)闭包与模块
一些很重要的说明:前面三篇博客详细的介绍了,引擎与编译器和作用域的关系,重点需要理解的是编译器中的分词与词法分析,JavaScript的特有的“赋值操作的左右侧”引用操作:编译阶段的词法作用域的工作原 ...
- javascript从作用域到闭包-笔记
读<你不知道的javascript>一书做个笔记;编译原理: js是一门编译型的语言,与传统编译语言类似,传统编译的过程分为三个阶段 ; 1. 分词/词法分析; 2.解析/语 ...
- 剖析JavaScript函数作用域与闭包
在我们写代码写到一定阶段的时候,就会想深究一下js,javascript是一种弱类型的编程语言,而js中一个最为重要的概念就是执行环境,或者说作用域.作用域重要性体现在哪呢?首先,函数在执行时会创建作 ...
- JavaScript之作用域与闭包详解
前言: JavaScript是一种应用非常广泛的语言,其也有一些自身特点和优势,本文重在讲述其作用域机制以及闭包,会从一些实例来探讨其机理. 作用域在JavaScript程序员日常使用中有不同的含义, ...
- JavaScript 函数作用域和闭包
函数作用域和闭包 词法作用域 它们在定义它们的作用域里运行,而不是在执行的作用域运行,但是只有在运行时,作用域链中的属性才被 定义(调用对象),此时,可访问任何当前的绑定. 调用对象 ...
随机推荐
- electron——dialog(实现导出excel)
背景 前端点击导出excel按钮后,请求完需要导出的数据后发送给主进程electron,由主进程保存到本地 dialog 显示用于打开和保存文件.警报等的本机系统对话框. dialog 模块提供了ap ...
- 找到了element, 但是用getText却得到空值,取不到文本的解决办法
最近代码中发现一些bug, 在Debug过程中发现,页面元素是被定位到了,但是用getText方法取到的却是空值.调查了一下发现,getText是否返回值和isDisplayed是否为true有关.当 ...
- CentOS7中安装MariaDB
什么是mariaDB? 在线安装(慢的要命) RPM离线安装(CentOS7.X) 在线安装 打开官方网站 https://mariadb.org/ 点击Download,跳转到下一页面 继续点击Do ...
- 2019-9-11:渗透测试,基础学习,vim编辑器,笔记
Linux快捷路径符号说明. 代表当前目录.. 上级目录- 代表前一个工作目录~ 表示当前用户的家目录 vmware tools 用来虚拟机和宿主机之间移动数据 vim/vi编辑器vim编辑器三种模式 ...
- Fortran流程控制与逻辑运算、循环--xdd
1.IF语句 1 if() then ... end if 2 if() then ... else ... end if 3 if() then ... else if() then ... els ...
- 设计模式之工厂模式(Factory)
转载请标明出处:http://blog.csdn.net/shensky711/article/details/53348412 本文出自: [HansChen的博客] 设计模式系列文章: 设计模式之 ...
- String对象常量池
对象池的主要目的是实现数据的共享处理, 在java之中对象池可以分为两种: 1.静态常量池 :指*.class加载时会自动将此程序之中保存的 字符串.普通的常量.类和方法的信息等全部经行分配 2.运行 ...
- 小程序如何判断用户(后台使用Django)
小程序如何判断用户是哪个: 有Web开发经验的都知道,客户端用户发起请求,服务器收到请求后,可以通过把用户user_id记录到session里,然后下次通过session里面的user_id来辨别是哪 ...
- P1055 ISBN号码
题目描述 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括99位数字.11位识别码和33位分隔符,其规定格式如x-xxx-xxxxx-x,其中符号-就是分隔符(键盘上的减号),最后一位 ...
- CSS+HTML实现移动端div左右滑动展示
由于手机屏幕的宽度有限,内容太多移动设备一行装不下的,所以很多移动端网站的导航栏都有左右滑动效果,下面我就用CSS+HTML实现移动端div左右滑动展示. CSS:box设置文本不换行,子元素box1 ...