JavaScript
写在最前
基于 Marijn Haverbeke 的 Eloquent JavaScript 编写
JavaScript 和 Java 没有任何关系,这个名字是为了蹭 Java 的热度
|
值,类型,操作符
数字,64 位,包括小数
算术,%
是取余
特殊的数:Infinity
,-Infinity
,NaN
字符串有三种方式:``, ””, '',使用 Unicode,特殊字符需要 \ 转义,第一个中可以使用 ${100 / 2} 等模板字面义
typeof
操作符输出类型,如 typeof 4.5
布尔值,注意 NaN != NaN
逻辑操作:$$
,||
,短路
三元运算符:? :
空值:null
和 undefined
,注意 null == undefined
自动类型转换,如 “” == false
如果在比较时不想要自动类型转换,则使用 ===
和 !==
,如 “” !== false
程序结构
语句有时可以不用分号隔开,但保险起见还是都用分号隔开
绑定,或变量:let a = 5;
;还有另一种写法 var
,是老式的写法,和 let
的区别在于作用域只限定于函数,而 let
支持块作用域。通常无脑使用 let
常量使用 const
,注意是其指向的对象固定,即可以向一个 const
列表中添加元素
未赋初值的绑定的值是 undefined
绑定名称可以使用 $ 和 _
if
、while
、for
、break
、switch-case
命名推荐使用驼峰命名法,如 JavaScript
函数
定义函数有三种方法:
|
可以在函数中定义函数
参数是可选的,即可以传递过多或过少的参数
|
也可以设置参数默认值
闭包:把函数视为值,返回函数,如
|
数据结构:对象和阵列
定义列表:let listOfNumbers = [0, 1, 2, 3, 4];
属性,如 listOfNumbers.length
访问属性的方法有两种,还有一种是 listOfNumbers["length"]
,注意这个会计算方括号内的表达式
对象还有方法,如 listOfNumbers.push(5);
对于列表,尾部操作:push()
、pop()
,头部操作:shift()
、unshift()
对象的定义类似于函数
|
可以后续添加属性:day1["finished"] = true;
delete
可以用于删除某个属性
Object.keys()
函数可以返回属性名的列表,用其可以遍历所有属性
Object.assign()
函数从其他对象复制所有属性到某个对象上
注意在对象的比较时只有两个绑定指向同一个实体时 ==
才会返回 true
,即 JavaScript 中没有深度比较
数组的遍历有简单的方法:
|
反过来已知值获取索引有 .indexOf()
和 .lastIndexOf()
方法,还有切片方法:.slice()
对于字符串,有 .trim()
,.padStart()
,repeat()
,.join()
,.split()
等方法终于有类似 Java 的地方了
可以使用剩余参数 ...
来接收任意个数的参数,如
|
也可以使用这个记号展开列表:
|
Math 对象提供了很多有用的数学函数,如 Math.random()
可以解析列表:
|
对象也适用:let {name} = {name: "Faraji", age: 23};
JSON 文件可用于序列化数据,与 JavaScript 的对象格式基本一致不然为什么叫 JavaScript Object Notation,但是名称必须用引号,如
|
可以使用 JSON.stringify()
将数据转化为 JSON 字符串格式;使用 JSON.parse()
则转化 JSON 字符串为 JS 对象
高阶函数
传递函数为参数
filter()
、map()
、reduce()
等取代循环的方法
对象生命的秘密
封装,方法
原型:可以用 Object.getPrototypeOf()
获取某对象的原型,原型定义为属性 .prototype
所有对象的最终原型都是 Object.prototype
使用 Object.create()
创建一个特定的原型
可以直接把函数作为类,也可以显示编写类:
|
注意到类中可以有方法,但没有属性,必须后面手动设定,如
|
原型属性可以被覆盖
JS 中还有映射类 Map
,相当于字典,有方法 has()
、set()
、get()
多态:例如可以重载 toString
:
|
属性名称实际上不是字符串,而是 Symbol
可迭代对象有一个 Symbol.iterator
方法,其有一个 next
方法,返回 value-done
对
一些似乎可以“直接”访问的属性其本质上也通过了函数调用,如 .size
;定义方法为在方法名前加 get
或 set
继承,如 class SymmetricMatrix extends Matrix
调用父类的方法则使用 super
instanceof
返回是否是某个类的实例,所有对象都是 Object
的实例
Bug 和错误
在程序或函数开头可以加上 “use strict”
进入严格模式,此处 JS 语法更严格
JavaScript 的强类型版本——TypeScript
编写测试
对于出错,可以返回一个特殊值,如 null
、undefined
、-1
抛出异常:throw new Error("message");
捕捉异常:
|
注意这会捕捉所有异常,如果想要捕捉特定类型的异常,可以
|
正则表达式
两种写法:
|
调用:test("")
、exec()
、search()
、replace()
模块
模块,包
包管理器的 NPM
CommonJS 的引入模块方案:const ordinal = require("ordinal")
新版的方案:
|
可能会使用某些 JS 方言编写,在发布时为了兼容性,会编译为较老版本的 JS
因为一个个小的模块不方便传输,所以通常会在发布时合并成较大的模块,叫做 bundling
为了节省空间,在发布时可能删除空格和注释,替换代码等,叫 minifier
异步编程
JavaScript 完全使用单线程
回调 callback 函数:当动作结束时调用函数,如 setTimeout(() => console.log("Tick"), 500);
JS 中是可能在某个时刻完成并产生某个值的异步 action,创建的办法是 Promise.resolve()
.then()
在 promise 产生一个值的时候调用回调函数
|
对于异步中的异常,有 Promise.reject
() 函数
对于 promise 集合,Promise.all()
返回一个等待所有 promises 被解决并产生值的 promise
可以像同步一样异步编程,只需要在函数之前加上 async
,等待获得的值前加上 await
,如
|
可以暂停和恢复的函数类似于异步,但是没有 promise,这种函数叫 generator,只有在调用 .next()
时才会产生下一个值,其在 function
后加上 *
,使用 yield
返回数据,如 iterator 可以简化为
|
异步调度
JavaScript 和浏览器
html 中的标签:<script> </script>
浏览器中环境隔离
文档对象模型
DOM 类似于一棵树的结构
书上的一些遍历操作:.childNodes
、ELEMENT_NODE
获取元素:.getElementsByTagName("a")
或 .getElementById("")
改变文档:
- 删除
.remove()
- 添加
.appendChild()
- 替换
.replaceChild(新结点,被替换结点)
- 插入
.insertBefore(新结点,插入结点)
- 创建结点
.createTextNode()
可以使用 .getAttribute()
和 .setAttribute()
操作元素的属性
调整布局:.offsetWidth
、offsetHeight
、clientWidth
、clientHeigtht
访问 style
属性修改样式
css
动画:requestAnimationFrame()
.querySelectorAll()
和 .querySelector()
与 .getElementByTagName()
等不同,其返回的对象不是活着的,即当改变文档时不会改变。且依旧不是一个真的数组,需要使用 Array.from()
处理事件
一个点击的例子:
|
第二个参数就是一个 event handler
事件对象可能有一些信息,如
|
事件处理器按照从小到大的顺序发生,如果想要阻止传递,使用 event.stopPropagation()
很多事件已经定义了默认行为,可以使用 event.preventDefault()
显示阻止该事件的默认行为
键盘:keydown
、keyup
、ctrlKey
、metaKey
属性等
对于指针,有 clientX
等属性
scroll 事件
focus 事件
load 事件
用 canvas 画图
有两种画图的方式:Scalable Vector Graphics(SVG) 和 canvas,这里主要介绍 canvas
canvas 有两种支持的绘画风格:2d
和 webgl
,后者通过 OpenGL 接口画三维图形,这里只讨论 2d
通过 getContext
方法创建上下文:
|
path 是线的序列,回自动闭合,可以通过控制路径来画图形的轮廓,如下面是一个三角形:
|
HTTP 和窗体
浏览器发送的 request 类似于:
|
服务器的 respond 类似于:
|
一个使用 fetch
获取信息的例子:
|
浏览器一般有沙盒保护,不允许跨域请求
有以下场景的 form 类型:text
、password
、checkbox
、radio
(多选域)、file
(允许用户从计算机上选择文件)
<textarea>
用于多行文本域
<select>
tag 配合 <option>
可供选择
当一个文本域被 focus 时,可以输入文本
disabled
显示灰色,表示无法被选中,可以直接使用,如
|
一个简单的 form:
|
change
事件只在域失去焦点时才会触发
一个从用户选择的文件中读取数据的例子:
|
localStorage
对象用于在客户端侧储存数据:
|
Node.js
除了浏览器以外,另一个可以运行 JavaScript 的环境
使用方法:node hello.js
注意 process.argv
的第一个参数是 node
,第二个是文件名(*.js
)
使用 CommonJS 的模块系统,支持相对路径和绝对路径,默认为查找 node_modules/
中的模块
npm 可用于安装包
注意依赖中的版本号如 ^2.3.0
表示支持至少为 2.3.0
且小于 3.0.0
的版本
与浏览器不同,Node.js 运行我们读写文件,如
|
支持 http 模块:
这是一个客户端:
|