第一部分:作用域和闭包

不要满足于只是让代码正常工作,而是弄清楚为什么是这样

作用域是什么


定义的变量存储在哪里?程序是如何找到变量的?实现的 规则就是作用域

传统编译语言执行前的编译三步骤(p5)

  1. 分词/ 词法分析(Tokenizing/ Lexing)
  2. 解析/ 语法分析 (Parsing)
  3. 代码生成

理解作用域

  1. 引擎--负责编译与执行整个过程
  2. 编译器 -- 语法分析与代码生成等
  3. 作用域 -- 收集并维护声明的变量查询,确定标识符的访问权限

LHS和RHS

含义是赋值操作的左侧或者右侧,并不一定是“=赋值操作符的左侧或者右侧”,因此在概念上可以理解为“赋值的对象是谁(LHS)”和“谁是赋值操作的源头(取源RHS)”

  1. // 练习
  2. // 请问引擎和作用域通话,分别进行了多少次LHS和RHS查询
  3. // 请指出
  4. function foo (a) {
  5. var b = a;
  6. return a + b;
  7. }
  8. var c = foo(2);
  9. 3LHS查询是
  10. me
  11. 1foo(..)赋值给c
  12. 2:隐式将2 赋值给 a
  13. 3a赋值给b
  14. 参考:
  15. c = ..、 a = 2(隐式变量分配)、b = ..
  16. 4RHS查询是
  17. me:
  18. 1:引擎通过作用域知道c是一个foo
  19. 2:引擎通过作用域知道foo是个函数
  20. 3:?
  21. 4return
  22. 参考:
  23. foo(2..、 = a a..、 ..b(return 处的a b 分别进行了一次RHS)

作用域嵌套

一个块或者函数嵌套在另一个块或者函数中就发生了作用域的嵌套。

嵌套作用域中的查询规则:“就近原则”,当前作用域中没有找到目标,则沿着原型链往外一层一层找,直到全局作用域。在全局作用域中未找到,查找停止,抛出异常。

区分LHS和RHS的重要性:变量未声明时,两种查询的行为不一样。

  1. function foo (a) {
  2. console.log(a + b);
  3. b = a;
  4. }

第一次在对b进行RHS查询时找不到该变量,引擎抛出ReferenceError错误;相较之下LHS查询在到不到时, “非严格模式”下会隐式创建全局变量,比如 b = a

  • ReferenceError 同作用域判别失败相关, 而 TypeError 则代表作用域判别成功了, 但是对结果的操作是非法或不合理的

词法作用域


函数作用域和块作用域


函数作用域的含义是指,属于这个函数的全部变量都可以在整个函数的范围内使用及复用。

我们都知道JS具有基于函数的作用域,(ES6出现了块级作用域)在函数内声明的变量和嵌套的函数都可以在函数内调用,外部不允许访问(符合最小特权原则)。这样设计的好处是能充分利用JavaScript 变量可以根据需要改变值类型的“ 动态” 特性。与此同时,还要避免隐式全局变量的声明。

规避冲突

全局命名空间

模块管理 (p26)

函数声明和函数表达式

两者之前最重要的区别是他们的名称标识符将会绑定在何处。

补充: 名称标识符

立即执行函数表达式IIFE( Immediately Invoked Function Expression)p28

块作用域

  1. with语句会创建
  2. try/catch 语句中catch分句会创建
  3. let关键字
  4. const关键字

提升是指声明会被视为存在于其所出现的作用域的整个范围内。

let声明的变量不会提升

  1. {
  2. console.log( bar ); // ReferenceError!
  3. let bar = 2;
  4. }

显示声明块级作用域

  1. // 使用{ } 显示声明let
  2. {
  3. let a = 0;
  4. console.log(a);
  5. }

const定义个一个块常量,定义之后不允许改变。

块作用域与垃圾回收

  1. function process(data) {
  2. // 在这里做点有趣的事情
  3. }
  4. // 1.内存可能没有释放
  5. var someReallyBigData = { .. };
  6. process( someReallyBigData );
  7. // 2.在这个块中定义的内容可以销毁了!
  8. //{
  9. // let someReallyBigData = { .. };
  10. // process( someReallyBigData );
  11. // }
  12. var btn = document.getElementById( "my_button" );
  13. btn.addEventListener( "click", function click(evt) {
  14. console.log("button clicked");
  15. }, /*capturingPhase=*/false );
  16. 由于 click 函数形成了一个覆盖整个作用域的闭包, JavaScript 引擎极有可能依然保存着someReallyBigData 取决于具体实现)。但是2. 声明了块作用域,引擎明确知道click函数不需要someReallyBigData ,使someReallyBigData 得内存占用得到释放。
  17. 为变量显式声明块作用域, 并对变量进行本地绑定是非常有用的工具

提升


概念:代码在执行前,声明(函数和变量)会都会在其作用域的顶端,可看做声明的变量或者函数移动到了作用域的最顶端。

  1. // 举例:
  2. {
  3. console.log(a) // undefined
  4. var a = 1
  5. }

引擎在执行前词法分析一步将上面代码看做 var a 声明和 a = 1 赋值两步,声明var a 将会被提升,因此在执行性console.log(a) 时, 引擎已经知道a,由于赋值保留在代码赋值的位置,所以a为undefined。如果a没有提升,浏览器将会报ReferenceError 错误。

注意:

  1. 函数表达式不会提升。

  2. 函数优先

    foo() // foo

    var foo;

    function foo () {

    console.log('foo')

    }

尽管 var foo定义在function foo ... 之前, 但由于function foo .. 函数声明优于变量声明, var foo 重复声明被忽略,因此 foo() 能够正确执行。如果var foo 变量在function foo 之前声明, 那么函数foo将作为重复声明而被忽略, 导致foo()执行包ReferenceError错误。

作用域闭包


读书笔记-you-don't-konw-js的更多相关文章

  1. 【js】【读书笔记】廖雪峰的js教程读书笔记

    最近在看廖雪峰的js教程,重温了下js基础,记下一些笔记,好记性不如烂笔头嘛 编写代码尽量使用严格模式 use strict JavaScript引擎是一个事件驱动的执行引擎,代码总是以单线程执行 执 ...

  2. 【第三周读书笔记】浅谈node.js中的异步回调和用js-xlsx操作Excel表格

    在初步学习了node.js之后,我发现他的时序问题我一直都很模糊不清,所以我专门学习了一下这一块. 首先我们来形象地理解一下进程和线程: 进程:CPU执行任务的模块.线程:模块中的最小单元. 例如:c ...

  3. 《javascript权威指南》读书笔记——第二篇

    <javascript权威指南>读书笔记——第二篇 金刚 javascript js javascript权威指南 今天是今年的196天,分享今天的读书笔记. 第2章 词法结构 2.1 字 ...

  4. 《javascript权威指南》读书笔记——第一篇

    <javascript权威指南>读书笔记——第一篇 金刚 javascript js javascript权威指南 由于最近想系统学习下javascript,所以开始在kindle上看这本 ...

  5. js读书笔记

    js读书笔记 基本类型的基本函数总结 1. Boolean() 数据类型 转换为true的值 转换为false的值 Boolean true false String 任何非空字符串 "&q ...

  6. Node.js高级编程读书笔记Outline

    Motivation 世俗一把,看看前端的JavaScript究竟能做什么. 顺便检验一下自己的学习能力. Audience 想看偏后台的Java程序员关于前端JavaScript的认识的职业前端工程 ...

  7. JavaScript、jQuery、HTML5、Node.js实例大全-读书笔记3

    技术很多,例子很多,只好慢慢学,慢慢实践!!现在学的这本书是[JavaScript实战----JavaScript.jQuery.HTML5.Node.js实例大全] JavaScript.jQuer ...

  8. JavaScript、jQuery、HTML5、Node.js实例大全-读书笔记2

    技术很多,例子很多,只好慢慢学,慢慢实践!!现在学的这本书是[JavaScript实战----JavaScript.jQuery.HTML5.Node.js实例大全] JavaScript.jQuer ...

  9. 读书笔记 - js高级程序设计 - 第十五章 使用Canvas绘图

    读书笔记 - js高级程序设计 - 第十三章 事件   canvas 具备绘图能力的2D上下文 及文本API 很多浏览器对WebGL的3D上下文支持还不够好   有时候即使浏览器支持,操作系统如果缺缺 ...

  10. 读书笔记_MVC__关于通过js构建ORM,实现Model层

    最近一直在学习MVC构建富应用的WEB程序,自己一直对MVC的设计模式理解的不是十分透彻,终于在研读了github上Spine的源码之后,对构建Model层有了一点自己的理解. 本文仅为个人理解,如有 ...

随机推荐

  1. Can't load IA 32-bit .dll on a AMD 64-bit platform错误的解决

    64位的系统,64位的myeclipse,64位的jdk,64位的tomcat,结果报错:Can't load IA 64-bit .dll on a AMD 32-bit platform,简直无语 ...

  2. MySQL学习笔记02_数据库和表的基本操作

    02_1 操作数据库 (1)创建数据库 CREATE DATABASE [IF NOT EXISTS] db_name [create_specification[, create_specifica ...

  3. 【转】《从入门到精通云服务器》第七讲—负载均衡和CDN技术

    在IDC知识中,我们常常会遇上负载均衡与CDN的概念而不知所云.第一讲[什么是云计算], 我们提到过负载均衡,仅给大家留下了印象.这次我们将深入浅出的讲讲到底什么是负载均衡与CDN技术.---互联网数 ...

  4. 【ORACLE】ORA-12537 问题整理

    ORA-12537主要是ORALCE 监听问题,今天帮同事处理问题时,他问道一种情况,开始连接很正常,后续多次出现ORA-12537问题 简单整理了下 一般请况下 1-检查数据库服务器是否没有启动监听 ...

  5. JSON相关知识,转载:删除JSON中数组删除操作

    一:JSON是什么 JSONg格式:对象是一个无序的“名称/值”对的集合. 对象以括号开始,括号结束. 名称冒号分隔值. "名称/值"之间用逗号分隔 例: var people = ...

  6. MongoDB的安装与设置MongoDB服务

    Mongo DB 是目前在IT行业非常流行的一种非关系型数据库(NoSql),其灵活的数据存储方式备受当前IT从业人员的青睐.Mongo DB很好的实现了面向对象的思想(OO思想),在Mongo DB ...

  7. 从问题看本质:socket到底是什么?

    一.问题的引入——socket的引入是为了解决不同计算机间进程间通信的问题 1.socket与进程的关系 1).socket与进程间的关系:socket   用来让一个进程和其他的进程互通信息(IPC ...

  8. 网络问卷调查js实现代码

    昨天一个同行妹纸写了一个网络问卷调查的效果,但是有bug,于是就来问我该如何解决这个bug.经过我的分析,bug主要还是出在复选框的那部分,经过修改,bug问题解决,现在贴出如下代码,仅供大家参考: ...

  9. mysql外键添加error1215

    在mysql创建表外键的过程中,由于操作不当,会提示cannot add foreign key constraint的错误. 造成此错误可能的原因如下: 1.数据类型不匹配,外键与其相关联的键必须数 ...

  10. mark

    *求数根公式:a的数根b = (a-1) % 9 + 1; *约瑟环问题:f1 = 0; 第i个(i>1),f = (f+m) %i;