《你不知道的JavaScript上卷》知识点笔记
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC" }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; min-height: 25.0px }
p.p3 { margin: 0.0px 0.0px 12.0px 0.0px; line-height: 14.0px; font: 18.0px "Songti SC"; color: #000000 }
p.p4 { margin: 0.0px 0.0px 12.0px 0.0px; line-height: 14.0px; font: 18.0px Times; color: #000000; min-height: 23.0px }
p.p5 { margin: 0.0px 0.0px 12.0px 0.0px; line-height: 14.0px; font: 18.0px Times; color: #000000 }
p.p6 { margin: 0.0px 0.0px 12.0px 0.0px; line-height: 14.0px; font: 18.0px "Songti SC"; color: #000000; min-height: 25.0px }
span.s1 { font: 18.0px Helvetica }
span.s2 { }
span.s3 { font: 18.0px Times }
span.Apple-tab-span { white-space: pre }
1、
尽管通常将JavaScript归类为“动态”或“解释执行”语言,但事实上他是一门编译语言。
2、传统编译语言编译流程:
1.分词/词法分析
2.解析/语法分析
3.代码生成
3.
对于JavaScript来说,大部分情况下编译发生在执行前的几微秒内,JavaScript引擎用尽了各种办法(比如JIT,可以延迟编译甚至实施重编译)来保证性能最佳
4.
变量的赋值操作会执行两个动作,首先编译器会在当前作用域中申明一个变量(如果之前没有声明过),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对它赋值。
5.
var a = 2; //LHS引用,写
console.log(a) //RHS引用,读
6.
var foo = function(){} //会进行LHS查询
7.
RHS查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出ReferenceError异常,而LHS不会(非严格模式下)
8.
ES5中引入了严格模式
9.
作用域共有两种主要的工作模型,第一种是最为普遍的,被大多数编程语言所采用的词法作用域。另一种叫做动态作用域,仍有一些编程语言在使用(比如bash脚本、Perl中的一些模式等)
10.
JavaScript使用词法作用域
11.
词法作用域是由你在写代码时将变量和快作用于写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变(大部分情况下)
12.
无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处的位置决定
13.
欺骗词法作用域会导致性能下降
14.
在严格模式的程序中,eval()在运行时有其自己的词法作用域,意味着其中的声明无法修改所在的作用域
15.
JavaScript中有两个机制可以“欺骗”词法作用域:eval()和with
这两个机制的副作用是引擎无法再编译时对作用域查找进行优化,因为引擎只能谨慎的认为这样的优化是无效的
16.
最小特权原则:应该最小限度地暴露必要内容,而将其他内容都“隐藏”起来,比如某个模块或对象的API设计
17.
模块只是利用作用域的规则强制所有标识符都不能注入到共享作用域中,而是保持在私有、无冲突的作用域中,这样可以有效规避掉所有的意外冲突
18.
如果没有函数名,当函数需要引用自身时只能使用已经过期的arguments.callee引用
19.
始终给函数表达式命名是一个最佳实践
20.
由于函数被包含在一对()内部,因此成为了一个表达式,通过在末尾加上另外一个()可以立即执行这个函数。IIFE
21.
表面上看JavaScript并没有块作用域
22.
with关键字,是块作用域的一个例子,用with从对象中创建出的作用域仅在with中而非外部作用域中有效
23.
try/catch的分句会创建一个块作用域,其中声明的变量仅在catch内部有效
24.
ES6引入了新的let关键字,可以将变量绑定到所在的任意作用域中(通常是{…}内部)
25.
块作用域可以让引擎清楚地知道没有必要继续保存块里面的数据了
26.
引擎会在解释JavaScript代码之前首先对其进行编译
27.
编译阶段中的一部分工作就是找到所有的声明,并用合适的作用域将它们关联起来,因此,包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理
28.
当你看到var a = 2;时,可能会认为这是一个声明,但JavaScript实际上会将其看成两个声明:var a;和a = 2; 第一个定义声明是在编译阶段进行的,第二个赋值声明会被留在原地等待执行阶段
29.
先有声明后有赋值
30.
每个作用域都会进行提升操作
31.
函数声明会被提升,但是函数表达式却不会被提升
32.
函数会首先被提升,然后才是变量
33.
出现在后面的函数声明会覆盖之前的函数声明
34.
所有的声明(变量和函数)都会被“移动”到各自作用域的最顶端,这个过程被称为提升
35.
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行
36.
无论通过何种手段将内部函数传递到所在的词法作用域以外,他都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包
37.
IIFE经典例子p49
38.
大多数模块依赖加载器/管理器本质上都是将这种模块定义封装进一个有好的API。p53
39.
模块模式的两个特点:为函数定义引入包装函数,并保证它的返回值和模块的API保持一致
40.
es6的模块没有“行内”格式,必须被定义在独立的文件中(一个文件一个模块)。
41.
export会将当前模块的一个标识符(变量、函数)导出为公共api,这些操作可以在模块定义中根据需要使用任意多次
42.
动态作用域并不关心函数和作用域是如何声明以及在何处声明的,只关心他们从何处调用
43.
箭头函数在涉及this绑定时的行为和普通函数的行为完全不一致,他放弃了所有普通this绑定的规则,取而代之的是用当前的词法作用域覆盖了this本来的值。
44.
函数内部代码this.count中的this并不是指向那个函数对象,所以虽然属性名相同,根对象却并不相同
45.
有一种传统的但是现在已经被弃用和批判的用法,是使用 arguments. callee 来引用当前正在运行的函数对象。这是唯一一种可以从匿名函数对象 内部引用自身的方法。然而,更好的方式是避免使用匿名函数,至少在需要 自引用时使用具名函数(表达式)。arguments.callee 已经被弃用,不应该再 使用它。
46.
每当你想要把this和词法作用与的查找混合使用时,一定要提醒自己,这是无法实现的。
47.
this是在运行时绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件,this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式
48.
当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象
49.
对象属性引用链中只有最顶层或者说最后一层会影响调用位置
50.
参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值
51.
回调函数丢失this绑定是非常常见的,调用回调函数的函数可能会修改this
52.
JavaScript提供的绝大多数函数以及你自己创建的所有函数都可以使用call()和apply()方法
53.
var bar = foo.bind(obj) //这样不管foo怎么执行,this都是指向obj。
bind()会返回一个硬编码的新函数,它会把参数设置为this的上下文并调用原始函数
54.
new是最后一种可以影响函数调用时this绑定行为的方法,我们称之为new绑定
55.
默认绑定,隐式绑定,显式绑定,new绑定
56.
判断this
1、函数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象 var bar = new foo()
2、函数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this绑定的是指定的对象 var bar = foo.call(obj2)
3、函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上下文对象 var bar = obj.foo();
4、如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到全局对象 var bar = foo()
57.
如果你把null或者undefined作为this的绑定对象传入call、apply或者bind,这些值在调用时会被忽略,实际应用的是默认绑定规则
58.
Object.create(null)和null很像,但是并不会创建Object.prototype这个委托,所以它比{}更“空”
59.
箭头函数不使用this的四种标准规则,而是根据外层(函数或者全局)作用域来决定this
60.
如果要判断一个运行中函数的this绑定,就需要找到这个函数的直接调用位置,找到之后按56条的规则来判断
61.
对象可以通过两种形式定义:声明(文字)形式和构造形式
62.
简单基本类型(string, boolean, number, null和undefined)本身并不是对象,对null执行typeof null时会返回字符串“object”,实际上,null本身是基本类型
63.
JavaScript内置对象:String, Number, Boolean, Object, Function, Array, Date, RegExp, Error
64.
检查对象类型:Object.prototype.toString.call(strObject)
65.
存储在对象容器内部的是这些属性的名称,它们就像指针一样,指向这些真正的存储位置
66.
ES6中增加了可以算属性名,可以在文字形式中使用[]包裹一个表达式来当做属性名
67.
即使你再对象的文字形式中声明一个函数表达式,这个函数也不会“属于”这个对象——它们只是对于相同函数对象的引用
68.
如果你试图向数组添加一个属性,但是属性名“看起来”像一个数字,那么它会变成一个数值下标(因此会修改数组的内容而不是添加一个属性)
69.
相比深复制,浅复制非常易懂并且问题要少的多,所以ES6定义了Object.assign()方法来实现浅复制,Object.assign()就是使用=操作符来赋值
70.
结合writable:false和configurable:false就可以创建一个真正的常量属性(不可修改、重定义或者删除)
71.
如果你想禁止一个对象添加新属性并且保留已有属性,可以使用Object.preventExtensions()
72.
in操作符会检查属性是否在对象及其prototype原型链中,相比之下,hasOwnProperty()只会检查属性是否在对象中
73.
4 in [2, 4, 6]的结果并不是你期待的true,因为[2, 4, 6]这个数组中包含的属性名是0、1、2没有4
74.
forEach()会遍历数组中的所有值并忽略回调函数的返回值。every()会一直运行直到回调函数返回false(或者“假”值)
some()会一直运行直到回调函数返回true(或者“真”值)
75.
for..in遍历键
for..of遍历值
76.
在JacaScript中模拟类是得不偿失的,虽然能解决当前的问题,但是可能会埋下更多隐患
77.
任何可以通过原型链访问到(并且是enumerable)的属性都会被枚举
78.
继承以为这复制操作,JavaScript(默认)不会复制对象属性。相反,JavaScript会在两个对象之间创建一个关联,这样一个对象就可以通过委托访问另一个对象的属性和函数
79.
.constructor引用同样被委托给了原型,而原型的.constructor默认指向“创建这个对象的函数”
80.
实际上,new会劫持所有普通函数并用构造对象的形式来调用他
81.
在JavaScript中对于“构造函数”的最准确的解释是,所有带new的函数调用
82.
Object.create(Foo.prototype)会凭空创建一个“新”对象并把新对象内部的prototype关联到你指定的对象(本例中是Foo.prototype),换句话说:创建一个新的Bar.prototype对象并把他关联到Foo.prototype
83.
Bar.prototype = Foo.prototype并不会创建一个关联到Bar.prototype的新对象,因此当你执行类似Bar.prototype.myLabel = …的赋值语句时会直接修改Foo.prototype对象本身
84.
ES6可以使用Object.setPrototypeOf(Bar.prototype, Foo.prototype)
85.
a instanceof Foo回答的问题是:在a的整条prototype链中是否有指向Foo.prototype的对象
86.
prototype机制就是存在于对象中的一个内部链接,它会引用其他对象
87.
JavaScrpt机制有一个核心区别,那就是不会进行复制,对象之间是通过内部的prototype链关联的
88.
原型链换句话说就是对象之间的关联关系
89.
委托行为意味着某些对象在找不到属性或方法引用时会把这个请求委托给另一个对象
90.
如果对象关联风格的代码能够实现类风格代码的所有功能并且更加简洁易懂,那他是不是比类风格更好?
91.
行为委托关键: Object.create(obj)
92.
匿名函数缺点:
1.调试栈更难追踪
2.自我引用(递归、事件绑定等等)更难
3.代码更难理解
93.
行为委托认为对象之间是兄弟关系,互相委托,而不是父类和子类的关系
94.
对象关联是一种编码风格,他倡导的是直接创建和关联对象,不把他们抽象成类
《你不知道的JavaScript上卷》知识点笔记的更多相关文章
- Vim 命令图解-Gvim使用笔记-2017-5-9
Vim 命令图解-Gvim使用笔记... 图片要是看的不太清楚推荐使用:鼠标右键在新标签中打开或是全屏看图 Vim中常用的一些速查命令: Vim发展历史:1976年Bill Joy开发了vi1988 ...
- Vim 命令图解-Gvim使用笔记
Vim 命令图解-Gvim使用笔记... 参考的网址:http://blog.vgod.tw/wp-content/uploads/2014/08/vgod-vim-cheat-sheet-full. ...
- Python 入门必学经典知识点笔记【肯定有你不知道的】
前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:实验楼 Python 作为近几年越来越流行的语言,吸引了大量的学员开始学 ...
- [新手必备]Python 基础入门必学知识点笔记
Python 作为近几年越来越流行的语言,吸引了大量的学员开始学习,为了方便新手小白在学习过程中,更加快捷方便的查漏补缺.根据网上各种乱七八糟的资料以及实验楼的 Python 基础内容整理了一份极度适 ...
- Java 多线程与并发【知识点笔记】
Java 多线程与并发[知识点笔记] Java多线程与并发 先说一下线程与进程的由来: 在初期的计算机,计算机只能串行执行任务,并且需要长时间的等待用户的输入才行 到了后来,出现了批处理,可以预先将用 ...
- 《图解http》知识点笔记
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica } p.p2 { margin: 0.0px 0.0px 0.0px 0. ...
- 图解HTTP学习笔记
前言: 一直觉得自己在HTTP基础方面都是处于知其然,不知其所以然的样子.最近利用空闲时间拜读了一下图解HTTP,写篇博客记录一下读书笔记. TCP三次握手: ① 发送端首先发送一个带SYN标志的数据 ...
- 图解http学习笔记【一】
不想单纯的把书里的知识点罗列一遍 这周,我们的安全代码终于改完了.我在微信上报了个叫 一修读书的课程,现在已经听了6天.感觉并不是很神奇,聊胜于无.倒是趁着当当搞活动买回来好几本书,其中就有这本图解h ...
- 图解HTTP学习笔记——简单的HTTP协议
简单的HTTP协议 前言 最近在学习Web开发的相关知识,发现<图解HTTP>这本书通俗易懂.所以花时间学习这本书,并记录下学习笔记. 如上图,我们每天都在浏览网页,一般我们都是在浏览器地 ...
- 图解http读书笔记
以前对HTTP协议一知半解,一直不清楚前端需要对于HTTP了解到什么程度,知道接触的东西多了,对于性能优化.服务端的配合和学习中也渐渐了解到了HTTP基础的重要性,看了一些大神对HTTP书籍的推荐,也 ...
随机推荐
- 聚簇(或者叫做聚集,cluster)索引和非聚簇索引
字典的拼音目录就是聚簇(cluster)索引,笔画目录就是非聚簇索引.这样查询“G到M的汉字”就非常快,而查询“6划到8划的字”则慢. 聚簇索引是一种特殊索引,它使数据按照索引的排序顺序存放表中.聚簇 ...
- python2 与python3的变化
1 写文件如果是bytes类型的话,打开文件 open参数设置为wb 2 python2 默认包import是相对路径,python3是绝对路径 3 python3的dict没有has_key方法,用 ...
- Head First设计模式之解释器模式
一.定义 给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子. 主要解决:对于一些固定文法构建一个解释句子的解释器. 何时使用:如果一种特定类型的问题发生的频率足 ...
- 使用performance monitor 查看 每一个cpu core的cpu time
使用performance monitor 查看 每一个cpu core的cpu time: 打开performance monitor,添加 counter 如下 运行一段cpu bound 的代码 ...
- ts中interface与class的区别
interface -- 接口只声明成员方法,不做实现. class -- 类声明并实现方法. 那么接口有什么用呢?设想如下需求: 要实现一个print函数,它将传入的对象打印出来.在实际实现上,它将 ...
- 使用dropwizard(4)-加入测试-jacoco代码覆盖率
前言 dropwizard提供了一个简单的测试框架.这里简单集成并加入jacoco测试. Demo source https://github.com/Ryan-Miao/l4dropwizard 本 ...
- Hyperledger Fabric 本地运行的简单示例
环境: Ubuntu 16.04 go 1.7.4 版本: Fabric v1.0.0-alpha 本文主要目的就是让大家体验以下Fabric网络环境搭建的具体过程,不基于集成化脚本手动搭建. 一.编 ...
- Maven 环境配置
1. 解压maven 2. 配置MAVEN_HOME环境变量 MAVEN_HOME D:\maven\apache-maven-3.0.5-bin\apache-maven-3.0.5 path ...
- 汇编转移指令jmp原理
在计算机中存储的都是二进制数,计算机将内存中的某些数当做代码,某些数当做数据.在根本上,将cs,ip寄存器所指向的内存当做代码,指令转移就是修改cs,ip寄存器的指向,汇编中提供了一种修改它们的指令- ...
- Codeforces #448 Div2 E
#448 Div2 E 题意 给出一个数组,有两种类型操作: 选定不相交的两个区间,分别随机挑选一个数,交换位置. 查询区间和的期望. 分析 线段树区间更新区间求和. 既然是涉及到两个区间,那么对于第 ...