第一部分 作用域与闭包

第一章 作用域是什么

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(上)作用域与闭包的更多相关文章

  1. 你不知道的JavaScript(作用域和闭包)

    作用域和闭包 ・作用域 引擎:从头到尾负责整个JavaScript的编译及执行过程. 编译器:负责语法分析及代码生成等. 作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非 ...

  2. 我认知的javascript之作用域和闭包

    说到javascript,就不得不说javascript的作用域和闭包:当然,还是那句老话,javascript在网上都说得很透彻了,我也就不过多的强调了: 作用域:javascript并没有像其他的 ...

  3. 读书笔记-你不知道的JavaScript(上)

    本文首发在我的个人博客:http://muyunyun.cn/ <你不知道的JavaScript>系列丛书给出了很多颠覆以往对JavaScript认知的点, 读完上卷,受益匪浅,于是对其精 ...

  4. 你不知道的JS之作用域和闭包 附录

     原文:你不知道的js系列 A 动态作用域 动态作用域 是和 JavaScript中的词法作用域 对立的概念. 动态作用域和 JavaScript 中的另外一个机制 (this)很相似. 词法作用域是 ...

  5. 你不知道的JS之作用域和闭包(五)作用域闭包

    原文:你不知道的js系列 一个简单粗暴的定义 闭包就是即使一个函数在它所在的词法作用域外部被执行,这个函数依然可以访问这个作用域. 比如: function foo() { var a = 2; fu ...

  6. javascript的作用域和闭包(三)闭包与模块

    一些很重要的说明:前面三篇博客详细的介绍了,引擎与编译器和作用域的关系,重点需要理解的是编译器中的分词与词法分析,JavaScript的特有的“赋值操作的左右侧”引用操作:编译阶段的词法作用域的工作原 ...

  7. javascript从作用域到闭包-笔记

    读<你不知道的javascript>一书做个笔记;编译原理:    js是一门编译型的语言,与传统编译语言类似,传统编译的过程分为三个阶段 ;     1. 分词/词法分析; 2.解析/语 ...

  8. 剖析JavaScript函数作用域与闭包

    在我们写代码写到一定阶段的时候,就会想深究一下js,javascript是一种弱类型的编程语言,而js中一个最为重要的概念就是执行环境,或者说作用域.作用域重要性体现在哪呢?首先,函数在执行时会创建作 ...

  9. JavaScript之作用域与闭包详解

    前言: JavaScript是一种应用非常广泛的语言,其也有一些自身特点和优势,本文重在讲述其作用域机制以及闭包,会从一些实例来探讨其机理. 作用域在JavaScript程序员日常使用中有不同的含义, ...

  10. JavaScript 函数作用域和闭包

    函数作用域和闭包  词法作用域   它们在定义它们的作用域里运行,而不是在执行的作用域运行,但是只有在运行时,作用域链中的属性才被 定义(调用对象),此时,可访问任何当前的绑定.   调用对象     ...

随机推荐

  1. 如何打造一款m3u8视频爬虫

    0.前言 m3u8是一种很常见的网页视频播放器的视频源,比如说中国大学MOOC中课程就是使用了该种视频格式. 随便打开一门课程,就可以发现在网络请求中存在一个m3u8的文件,在preview中预览,它 ...

  2. Mac下载ChromeDriver

    ChromeDriver下载地址: https://npm.taobao.org/mirrors/chromedriver 如何查看chrome版本与ChromeDriver版本对应 查看chrome ...

  3. 探索 IPv6 网络

    目录 0x00 前言 0x01 探索 服务器配置 IPv6 地址 服务器部署网络代理 客户端配置网络代理 测试访问 IPv6 地址 给博客添加 IPv6 地址 0x00 前言 IPv4 地址枯竭的事情 ...

  4. Linux三个比较特殊的权限

    Linux还有三个比较特殊的权限,分别是:setuid,setgid,stick bit . -:表示一般文件 d:表示目录文件 l:表示链接文件 b:表示块设备 c:表示字符设备 p:表示管道 s: ...

  5. centOS系统安装-RabbitMq

    前言 消息通知机制是我们在日常业务开发总常常都会遇到:在微服务架构里,消息也是必不可少的,我们可以借助它异步实现很多业务,就拿我们日常的购物需求来说,在我们下单支付之后,我们就可以通过消息机制来异步处 ...

  6. 小白的springboot之路(六)、跨域解决方案CORS

    0-前言 前后端分离.分布式集群,经常都会涉及到跨域访问,而浏览器基于同源策略,正常情况下是不能跨域的,这就需要我们解决跨域访问问题:spring boot解决跨域也比较简单: 1-CORS跨域解决方 ...

  7. JAVA中空指针异常报错的几种可能坑你的情况

    一.局部变量覆盖掉其他变量导致无法使用. 在做Java客户管理的项目的时候,eclipse报出了个空指针异常的错误,但反复检查也并没感觉出错误,调用的数组给它初始化而且赋值了,但是编译器很顽强的报了一 ...

  8. javascript实用Date工具

    时间字符串和年月日数据之间的自由转换工具:2018年更新版 上代码: /** * @Desc: 时间处理工具 * @Author: 拿饭盒当烟灰缸 * @Date: 2018-02-27 15:42: ...

  9. shell一键部署nginx+tomcat

    1.首先拉取环境  tomcat需要用到jdk环境 提前准备好nginx源码包,放于指定目录下 vim test.sh #!/bin/bash yum -y install gcc gcc-c++ z ...

  10. Leecode_98_Validate_Binary_Search_Tree

    Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...