你不知道的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 函数作用域和闭包
函数作用域和闭包 词法作用域 它们在定义它们的作用域里运行,而不是在执行的作用域运行,但是只有在运行时,作用域链中的属性才被 定义(调用对象),此时,可访问任何当前的绑定. 调用对象 ...
随机推荐
- 基于crypto++国产加密软件SM4的实现,顺带加了ase,base64
唔,美国压制得越狠,各种替代产品就越能活. 本文分享SM4的一种快速实现与集成方式. SM4(原名SMS4)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于201 ...
- linux用户资源控制
/etc/security/limits.conf配置文件详解 这个文件主要是用来限制用户对资源的使用.是/lib64/security/pam_limits.so模块对应的/etc/serurity ...
- day20191120笔记
1.spring的优势 U盘拷.总结.微信公众号:.2.笔试,课前默写,默完之后要回答问题.3.微服务,带着,知识点,卷子.ssm整个东西讲一下.面试是综合能力.背面试题. 通过基础很重要.学精烂熟于 ...
- petri 网理论与研究(第一节140915)
成绩 :70 大作业 和 30 的最后讨论 petri 是一个人的名字. 网状结构的信息流模型,和自动机有点像 理论体系发展比较慢 应用很远 1 EN,P/T,Pr/T,CPN,关系网……
- SpringBoot 使用IDEA 配置热部署
在开发中稍微更改一点内容就要重启,很麻烦.这个时候使用Spring Boot的热部署就能解决你的问题. 上图: 1,在pom.xml文件中添加依赖: <dependency> <gr ...
- 作为UIApplication单例对象的方法 openURL方法的变化
作为UIApplication单例对象的方法 openURL: 在iOS开发中经常用来实现在当前应用打开外部链接的需求比如跳转到其他应用,跳转应用隐私设置界面;还有相关API canOpenURL: ...
- 如何解决jpa 要求column 名称单词必须用下划线
[转]:http://www.jeesns.cn/article/detail/6657 先引出轮子http://blog.csdn.net/54powerman/article/details/76 ...
- JQuery动态添加控件并取值
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- js对象可扩展性和属性的四个特性(上)
# js对象可扩展性和属性的四个特性(上) 一.前言 再次花时间回顾一下基础,毕竟要想楼建的好,地基就要牢固,嘻嘻! 在开始之前需要具备对prototype.__proto__.constructor ...
- Delphi - 调用SuperDll 持续更新
调用SuperDll 接上一篇Delphi创建Superdll,将生成的SuperDll.dll文件复制到本工程路径下,创建如下代码进行Superdll各个接口的测试. 创建uSuperDll.pas ...