2021年5月找到了一家公司实习,离实习上班还有两个多月的时间,就给了我们一个任务:阅读犀牛书(《JavaScript权威指南》第七版)和红宝书(《JavaScript高级程序设计》第四版)。这两本书,在很久之前就听说过,但由于各种各样的原因没有去阅读这两本书,现在刚刚好有机会拜读这两本书,就利用这段时间好好看这两本书。
以下是阅读JavaScript权威指南的归纳和总结,根据书本的章节来分点,主要是简单描述这一章节的内容,摘取重要的知识点,以及自己以前掌握不够牢固的部分。
这一章节简单介绍了一下JavaScript这门语言特点,举了个简单的例子,以及每个章节的内容介绍。
主要内容是文本、注释、字面量、标识符、保留字、Unicode和可选分号。
文本:JavaScript区分大小写
注释:// 单行注释 /*多行注释*/
字面量:数值,字符串,布尔值,对象和数组
标识符:用来存储某个变量的引用
保留字:JavaScript自身使用的标识符
*Unicode:目前比较常用的编码格式,当程序源代码存在两种以上不同编码的字符时,最好要先进行归一化,如Unicode归一化。JavaScript默认源代码是归一化后的。
*可选分号:JavaScript代码行尾的;一般是可写可不写的,但特殊位置是要写的,因为JavaScript在解析时遇到无法识别为一行语句的时候会默认加“;”当一行跟下面一行代码是否为一行有歧义时一定要加“;”,还有涉及到return、throw、yield、break和continue和++、--以及箭头函数时。
讲解基本类型(少了数组和对象)
数值:
基本使用:
使用的是IEE 754的64位浮点数标准,可以分为整数和浮点数两类。二进制,八进制和十六进制分别使用0b、0o和0x前缀,如0xff。也可以使用科学计数法,数值后面e(或E)后面的数字为指数,如100 = 1.0e2。es6新特性可以加分隔符,如1_000。
算术:除了基本的+-*/%外,js还提供了很多的算术函数,都被封装到了Math类里面,具体函数如下:
abs(x) | 返回 x 的绝对值。 |
acos(x) | 返回 x 的反余弦值。 |
asin(x) | 返回 x 的反正弦值。 |
atan(x) | 以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。 |
atan2(y,x) | 返回从 x 轴到点 (x,y) 的角度(介于 -PI/2 与 PI/2 弧度之间)。 |
ceil(x) | 对数进行上舍入。 |
cos(x) | 返回数的余弦。 |
exp(x) | 返回 Ex 的指数。 |
floor(x) | 对 x 进行下舍入。 |
log(x) | 返回数的自然对数(底为e)。 |
max(x,y,z,...,n) | 返回 x,y,z,...,n 中的最高值。 |
min(x,y,z,...,n) | 返回 x,y,z,...,n中的最低值。 |
pow(x,y) | 返回 x 的 y 次幂。 |
random() | 返回 0 ~ 1 之间的随机数。 |
round(x) | 四舍五入。 |
sin(x) | 返回数的正弦。 |
sqrt(x) | 返回数的平方根。 |
tan(x) | 返回角的正切。 |
ES6还新增了一些函数,具体可以看书本28页。
数值还有两个特殊标识符,Infinity和NaN。Infinity表示无穷,正为无穷大,负为无穷小。NaN表示非数字的意思。
注意:浮点计算会有精度损失,如0.3-0.2 != 0.2- 0.1,这在其他高级语言也是一样的,原因是IEE754 浮点格式,涉及到计算机数据存储的底层原理。NaN不等于它自身,也就是说我们可以用a == a判断a是否为NaN。
文本:文本大多数用赋值字符串。“”、‘’和``可以相互嵌套使用。这个特性在需要字符串包含“‘`时特别好用。”和’基本用法一样,比较特殊的是``,这个叫模板字面量,在里面使用${}可以获取到该上下文的变量。`还可以作为标签化模板字面量。
字符串本身有大量的api供我们去使用:
charAt() | 返回指定索引位置的字符 |
charCodeAt() | 返回指定索引位置字符的 Unicode 值 |
concat() | 连接两个或多个字符串,返回连接后的字符串 |
fromCharCode() | 将 Unicode 转换为字符串 |
indexOf() | 返回字符串中检索指定字符第一次出现的位置 |
lastIndexOf() | 返回字符串中检索指定字符最后一次出现的位置 |
localeCompare() | 用本地特定的顺序来比较两个字符串 |
match() | 找到一个或多个正则表达式的匹配 |
replace() | 替换与正则表达式匹配的子串 |
search() | 检索与正则表达式相匹配的值 |
slice() | 提取字符串的片断,并在新的字符串中返回被提取的部分 |
split() | 把字符串分割为子字符串数组 |
substr() | 从起始索引号提取字符串中指定数目的字符 |
substring() | 提取字符串中两个指定的索引号之间的字符 |
toLocaleLowerCase() | 根据主机的语言环境把字符串转换为小写,只有几种语言(如土耳其语)具有地方特有的大小写映射 |
toLocaleUpperCase() | 根据主机的语言环境把字符串转换为大写,只有几种语言(如土耳其语)具有地方特有的大小写映射 |
toLowerCase() | 把字符串转换为小写 |
toString() | 返回字符串对象值 |
toUpperCase() | 把字符串转换为大写 |
trim() | 移除字符串首尾空白 |
valueOf() | 返回某个字符串对象的原始值 |
布尔值:除了true和false,JavaScript的任何值都能被转化为布尔值。undefined,null,-0,+0,NaN,‘’(空字符串)这些都是假性值,在需要布尔值的地方会转化为false,除了这几个外其他所有值都是真性值,即需要布尔值的地方会转化为true。
null与undefined:这个两个值区别不大,在开发中一般,只使用一种用来表示值不存在。如果一个变量只定义未赋值,它的值为undefined。
*符号:符号其实一个不会重复的变量引用,即使创建符号时使用的参数是同一个,返回的符号也是不一样的。
全局对象:全局对象是只JavaScript执行时最顶层的环境,全局变量和全局函数都是存储在这个全局变量中的。
类型转换:基本类型型之间的相互转换都有一定的规制,对象转换相对特殊,在需要数值的地方会调用自身的valueOf方法,如果是字符串就调用toString方法
变量声明:在非严格模式下,有三种定义方法。一是使用var关键字,这个定义的变量会提升作用域,提升到函数作用域。第二种方法是使用let关键字,这个关键字是ES6新增语法,是修复之前语法缺陷的,他具有块级作用域不会提升变量的的作用域。第三种方法是不用关键字直接赋值,这样会定义一个全局变量。在严格模式下,只能用var和let关键字定义变量,且在有一些地方,表现也不一样。PS:常量的定义是使用const。
*解构赋值:解构赋值是一个非常强大的功能,只要赋值表达式左右有相应的结构,就能进行拆解赋值。
表达式基本分为函数定义表达式,属性访问表达式,调用表达式,和创建表达式
函数表达式:使用关键字function,例如:function test(){.....}。或者使用箭头函数,例如() => {}
属性访问表达式:有两种访问方式,一位object.变量名,二位object[变量名]
调用表达式:函数就直接test(),如果是某个对象的方法,就object.test()。调用有个特殊语法,叫条件式调用,语法为object?.test(),这个主要是预防object是null或undefined导致程序报错,如果对象为null或undefined,这个调用的返回值为undefined。
操作符:操作符有算术操作符,逻辑操作符,赋值操作符,它们之间有优先级,在运行区间会根据它们之间的优先级,绝对它们的运算顺序。特殊操作符:eval,?:, ??, typeof, delete,await,void。这些操作符都有他们各自的作用。
语句与大多数编程语言相同,都是使用顺序,分支,循环结构。
条件语句最基本的是if(true){....} else if (true){....}else{.....},其余还有switch语言,配合case和break使用。
循环最主要的用法就是for(let i = 0;i < n;i++),除了这个for循环,还可以使用多种迭代器,如forEach, for of ,for in等。
JavaScript对象的原理是原型链继承,虽然ES6语法新出了class等语法,但是它们的底层原理是一样的。下面是我在网上找到的一张图:
需要注意的事prototype是函数特有的一个属性,它指向自己的原型空间,因此可以判断prototype来确定一个变量是否为函数。创建对象使用new关键字,ES5语法使用new一个函数对象来创建一个对象。在ES6语法中,就可以使用class关键字来定义一个类了。
在继承方面,ES5中,可以使用Object.create(o)来创建一个对象,这个对象继承o。也可以显示的指定o1._porto_ = o2.prototype继承另一个对象。ES6语法支持在创建类字面量的时候,使用extend关键字去继承一个对象。
创建一个数组可以使用数组字面量、Array()构造函数、Array.of()、Array.form()创建一个数组。
稀疏数组:稀疏数组就是数组元素下标不连续的数组,它的length属性也大于自身元素的个数。
数组方法:forEach,map,fitlter,find,findInde,every,some,reduce,flat,flatMap
数组实现栈队列操作:push,pop.shift,unshift
数组排序:sort,第一个参数可选,是一个函数,返回布尔值,根据布尔值进行排序。
函数不管在哪里定义都会被提升到顶部声明,所以我们可以在声明前面使用函数。这个是因为,JavaScript在执行前会先扫描一边程序,将函数和有些变量提升到顶部。
*拓展操作符:在函数表达式中参数列表使用,会讲剩余的参数全部收集到一个数组里面。如果是在函数调用中,
在JavaScript中类指的是class定义的类字面量。利用类可以创建一个新对象,这是ES6语法新增的内容,因为JavaScript本身的一些缺陷,我们在使用对象做继承等操作时有些麻烦,这个语法就是用来解决这些问题的,使JavaScript面向对象编程更加自然、方便。
构造函数:constructor,在类字面量中定义这个函数,new的时候会自动调用这个函数去初始化对象,如果自己不显式定义构造函数,系统会隐式定义一个默认的构造函数。
私有字段:类字面量中的字段前面加个#,会使这个字段变成私有的,私有的字段只有,自生派生的对象才有权限去使用。要注意的是私有字段要先声明,才能在构造函数使用。
相比java,python这些高级语言,JavaScript的类语法不够完善,但是语法标准一直在进步,相信将来,JavaScript的面向对象编程会变得更好。
闭包:如果直接引入其他的第三方库,与自己的代码在同样的环境下运行,全局变量很容易被污染,导致一些难以修复的问题,很难排查问题在哪里。为了解决这种问题大佬们研究除了闭包这个方法,闭包就是利用函数作用域和立即执行函数的特点实现的。将所有的代码都放在一个匿名函数里面,用立即执行函数包裹住,使这个函数在script文件被引入的时候立即执行。
模块:模块的基本原理就是闭包,在早期JavaScript标准还没有模块这个说法,先是webpack、node等工具实现了模块化,后面官方才实现模块化。官方语法主要是使用export和import关键字来导出导入模块。
集合Set:集合和数组类似,但与数组的不同的是,集合的元素是唯一的,集合的值不允许重复,也没有顺序和索引。
键值对Map:Map是键去到值的索引,一般情况下,查询速度很快。是牺牲了空间换取时间的策略。
定型数组:定型数组使JavaScript的语法有点像强类型语言
正则表达式:可以说用于匹配字符串的小型编程语言,正则表达式对文本有强大的模式匹配和搜索替换功能。
写这个总结的时候的时间是2021年7月9日,由于这段时间还在学校,还有很多事情要弄,如期末考试、期末作业和实训作业等,结果阅读进度特别慢,《JavaScript权威指南》只阅读完11章节,《JavaScript高级程序设计》还没有去看。虽然《JavaScript权威指南》只阅读了一半左右的内容,但是收获良多,后悔没早点去看这本书。这本书讲的内容不是很高级,但是非常系统,内容很细,非常的基础。特别推荐初学者或者刚转JavaScript语言的开发者去阅读这本书,这本书把JavaScript分成17个章节来讲,每个章节的内容跟重点都不一样。我之前学习的习惯是看视频,然后要用什么就去百度,虽然这样学得很快,但是也导致自己学到的技术点是很零散的,看了这本书很好的补了我自己的短板,系统学习了JavaScript,补充了很多的知识点,对JavaScript有了更深的了解。