# 类型与语法
# 值
# 数组
# 稀疏数组
1 | var a = [ ]; |
a [1] 实际上跟 undefined 还是有区别的
# 类数组
- 具有索引属性:类数组对象的元素以数字索引的方式存储,比如 obj [0]、obj [1] 等。
- 具有 length 属性:类数组对象通常拥有 length 属性,表示它包含的元素个数。
- 不是数组实例:类数组对象并不是 Array 的实例,所以它没有数组的一些内置方法,如 push ()、pop ()、map () 等。
# 值和引用
- 简单值(即标量基本类型值,scalar primitive)总是通过值复制的方式来赋值 / 传递,包括 null、undefined、字符串、数字、布尔、symbol、 bigint。
- 复合值(compound value)—— 对象和函数,则总是通过引用复制的方式来赋值 / 传递。
# 原生函数
- String()
- Number()
- Boolean()
- Array()
- Object()
- Function()
- RegExp()
- Date()
- Error()
- Symbol()
通过构造函数(如 new String (“abc”))创建出来的是封装了基本类型值(如 “abc”)的封装对象
1 | var a = new String( "abc" ); |
# 封装对象的包装和拆封
- JavaScript 会自动为基本类型值包装一个封装对象
- 拆封封装对象调用 valueOf 函数或者强制转换
1 | // 自动包装 |
# 异步与性能
# Promise
# Promise 信任问题
# Promise 调用过早
什么意思?通俗的解释就是一个任务有时同步完成有时异步完成
立即完成的 Promise(类似于 new Promise(function(resolve){ resolve(42); })
)也无法被同步观察到,也就是 then 之后的任务一定是会以异步的方式被调用
# Promise 调用过晚
Promise 创建对象调用 resolve (…) 或 reject (…) 时,这个 Promise 的 then (…) 注册的观察回调就会被自动调度。可以确信,这些被调度的回调在下一个异步事件点上一定会被触发
考虑下面这种情况
1 | p.then(function () { |
“C” 无法打断或抢占 “B”,这是因为 Promise 的运作方式。因为 “C” 的任务被注册到下一轮去了
tips:永远都不应该依赖于不同 Promise 间回调的顺序和调度 也就是对于一轮里面的 Promise 任务,不要假定这一轮任务的执行顺序
# Promise 未调用问题
这里优雅的解决办法可以通过 Promise.race
设置超时来实现
# Promise 建立信任
1 | var p = { |
上面的代码不符合预期且是同步执行的, 需要进行 Promise 的规范化
改造后的
1 | Promise.resolve(p) |
Promise.resolve(p)
如果 p 是一个 Promise 的话,直接就返回该 Promise,否则会对 p 进行规范化,保证符合 Promise 的规范
# 生成器
# 生成器产生值
# 可迭代协议
可迭代协议允许 JavaScript 对象定义或定制它们的迭代行为,例如,在一个 for..of
结构中,哪些值可以被遍历到。一些内置类型同时是内置的可迭代对象,并且有默认的迭代行为,比如 Array 或者 Map,而其他内置类型则不是(比如 Object)
要成为可迭代对象,该对象必须实现 [Symbol.iterator]()
方法
# [Symbol.iterator]
一个无参数的函数,其返回值为一个符合迭代器协议的对象
# 迭代器协议
# next(value?)
返回一个 IteratorResult
接口类型的对象
1 | // IteratorResult 接口类型 |
next
函数传递的 value 参数是可选的,传递给生成器 next
方法的值将成为相应 yield
表达式的值
# return(value?)
无参数或者接受一个参数的函数,并返回符合 IteratorResult
接口的对象,其 value 通常等价于传递的 value,并且 done 等于 true。调用这个方法表明迭代器的调用者不打算调用更多的 next (),并且可以进行清理工作。
# throw(exception?)
无参数或者接受一个参数的函数,并返回符合 IteratorResult
接口的对象,通常 done 等于 true。调用这个方法表明迭代器的调用者监测到错误的状况
# 迭代器实现
1 | var something = (function () { |
调用
1 | for (var v of something) { |
for..of
循环在每次迭代中自动调用 next (),它不会向 next () 传入任何值,并且会在接收
到 done:true 之后自动停止
# 生成器迭代器
# 示例
1 | function* myGenerator() { |
something
是生成器 并不是一个可迭代对象something()
会产生一个可迭代对象
1 | function *something() { |
# 异步迭代生成器
# 其他一些要点
Promise.resolve
用于规划化 Promise,如果传递给 resolve 的是一个 Promise 或者 thenable,这会对其进行展开Promise.reject
跟Promise.resolve
不同,reject 如果接受 Promise 或者 thenable 并不会对其进行展开,而是直接把这个内容当成 reject 的理由- try-catch 无法跨异步捕获错误
1 | function foo() { |
- 生成器函数第一次传递的 value 是无效的