第一部分 作用域与闭包

第一章 作用域是什么

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. Linux线上与本地的httpd搭建【制作本地yum源】

    当前时间 2019-10-24-10:53:12 制作本地yum源 我用的VMware Workstation 系统环境: CentOS 7.5 首先我们先要挂载系统镜像 [root@laopa ~] ...

  2. RabbitMQ的入门学习

    RabbitMq消息队列 参考:https://blog.csdn.net/hellozpc/article/details/81436980 什么是消息队列 MQ :message Queue ,实 ...

  3. ansible on aws linux 2

    1. 安装epel yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 2. 安 ...

  4. 都是为了生活组——‘’都是为了吃饭”微信小程序评价

    基于NABCD评论作品,及改进建议 1.根据NABCD评论,作品的选题 N(Need,需求) 纠结症是目前在年轻人身上普遍存在着的问题,食堂食物众多,每次在吃饭前都要纠结好久,大大浪费了时间,还容易产 ...

  5. Dart Learn Notes 02

    Functions Dart是一门面向对象的语言,所以即便是方法也是一个对象,它的类型是Function. 这就意味着方法可以指向变量,也可以作为方法中的参数供其他方法使用.甚至可以让 一个类作为一个 ...

  6. Java包package之间调用问题-cmd运行窗口编译运行

    问题:在使用了java包机制(package)后,编译出现错误:找不到或无法加载主类 xxx 的错误提示信息(各种编译不通过) 先给演示结果: 编译:javac -d classes src/a/He ...

  7. Java异常处理只有Try-Catch吗?

    今天,我们将讨论一个非常重要的主题-Java 中的异常处理.尽管有时可能会对此主题进行过多的讨论,但并非每篇文章都包含有用且相关的信息. Java 中最常见的异常处理机制通常与 try-catch 块 ...

  8. kafka官方的kafka-server-start.sh不能关闭kafka进程解决办法

    vi kafka-server-stop.sh 把PIDS=$(ps ax | grep -i 'kafka\.Kafka' | grep java | grep -v grep | awk '{pr ...

  9. 【数据结构】之串(C语言描述)

    串(字符串)是编程中最常用的结构,但 C语言 中没有“字符串”这种变量,只能通过字符数组的形式表示字符串. C语言 为我们提供了一个 string.h 的头文件,通过这个头文件,我们可以实现对字符串的 ...

  10. python_编程面试题

    使用递归方法对一个数组求最大值和最小值 """ 用递归算法求解一个数组的最大值和最小值 思路: 1.首先假设这个列表只有1个元素或两个元素 2.再考虑超过两个元素的情况, ...