本文共 3741 字,大约阅读时间需要 12 分钟。
Generator 是 ES6 中新增的语法,和 Promise ⼀样,都可以⽤来异步编 程
// 使⽤ * 表示这是⼀个 Generator 函数// 内部可以通过 yield 暂停代码// 通过调⽤ next 恢复执⾏function* test() { let a = 1 + 2; yield 2; yield 3; }let b = test();console.log(b.next()); // > { value: 2, done: false }console.log(b.next()); // > { value: 3, done: false }console.log(b.next()); // > { value: undefined, done: true }
从以上代码可以发现,加上 * 的函数执⾏后拥有了 next 函数,也就是说 函数执⾏后返回了⼀个对象。每次调⽤ next 函数可以继续执⾏被暂停的代 码。以下是 Generator 函数的简单实现
// cb 也就是编译过的 test 函数function generator(cb) { return (function() { var object = { next: 0, stop: function() { } }; return { next: function() { var ret = cb(object); if (ret === undefined) return { value: undefined, done: true }; return { value: ret, done: false }; } }; })(); }// 如果你使⽤ babel 编译后可以发现 test 函数变成了这样function test() { var a; return generator(function(_context) { while (1) { switch ((_context.prev = _context.next)) { // 可以发现通过 yield 将代码分割成⼏块 // 每次执⾏ next 函数就执⾏⼀块代码 // 并且表明下次需要执⾏哪块代码 case 0: a = 1 + 2; _context.next = 4; return 2; case 4: _context.next = 6; return 3; // 执⾏完毕 case 6: case "end": return _context.stop(); } } }); }
Promise
是 ES6
新增的语法,解决了回调地狱的问题Promise
看成⼀个状态机。初始是 pending
状态,可以通过函数 resolve
和reject
,将状态转变为 resolved
或者 rejected
状态,状态⼀旦改变就不能再次变 化。then
函数会返回⼀个 Promise
实例,并且该返回值是⼀个新的实例⽽不是之前的实 例。因为Promise
规范规定除了pending
状态,其他状态是不可以改变的,如果返回 的是⼀个相同实例的话多个 then
调⽤就失去意义了。 对于 then
来说,本质上可以 把它看成是flatMap
这⾥来解析⼀道题⽬ [] == ![] // -> true ,下⾯是这个表达式为何为true 的步骤
// [] 转成 true,然后取反变成 false[] == false// 根据第 8 条得出 [] == ToNumber(false) [] == 0// 根据第 10 条得出ToPrimitive([]) == 0// [].toString() -> '''' == 0// 根据第 6 条得出 0 == 0 // -> true
=== ⽤于判断两者类型和值是否相同。 在开发中,对于后端返回的 code , 可以通过 == 去判断
前者存储在栈上,后者存储在堆上
JS
是单线程的,所以setTimeout
的误差其实是⽆法被完全解决的,原因 有很多,可能是回调的,有可能是浏览器中的各种事件导致。这也是为什么⻚⾯开久了,定时器会不准的原因,当然我们可以通过⼀定的办法去减少这个 误差。
// 以下是⼀个相对准备的倒计时实现var period = 60 * 1000 * 60 * 2var startTime = new Date().getTime();var count = 0var end = new Date().getTime() + periodvar interval = 1000var currentInterval = intervalfunction loop() { count++ var offset = new Date().getTime() - (startTime + count * interval); // 代码 var diff = end - new Date().getTime() var h = Math.floor(diff / (60 * 1000 * 60)) var hdiff = diff % (60 * 1000 * 60) var m = Math.floor(hdiff / (60 * 1000)) var mdiff = hdiff % (60 * 1000) var s = mdiff / (1000) var sCeil = Math.ceil(s) var sFloor = Math.floor(s) currentInterval = interval - offset // 得到下⼀次循环所消耗的时间 console.log('时:'+h, '分:'+m, '毫秒:'+s, '秒向上取整:'+sCeil, '代码执⾏时间: setTimeout(loop, currentInterval) } setTimeout(loop, currentInterval)
[1, [2], 3].flatMap(v => v)// -> [1, 2, 3]
如果想将⼀个多维数组彻底的降维,可以这样实现
const flattenDeep = (arr) => Array.isArray(arr) ? arr.reduce( (a, b) => [...a, ...flattenDeep(b)] , []) : [arr]flattenDeep([1, [[2], [3, [4]], 5]])
这个问题通常可以通过
JSON.parse(JSON.stringify(object))
来解决
let a = { age: 1, jobs: { first: 'FE' } }let b = JSON.parse(JSON.stringify(a)) a.jobs.first = 'native'console.log(b.jobs.first) // FE
但是该⽅法也是有局限性的:
undefined
symbol
let obj = { a: 1, b: { c: 2, d: 3, }, }obj.c = obj.bobj.e = obj.aobj.b.c = obj.cobj.b.d = obj.bobj.b.e = obj.b.clet newObj = JSON.parse(JSON.stringify(obj))console.log(newObj)
在遇到函数、 undefined 或者 symbol 的时候,该对象也不能正常的序列 化
let a = { age: undefined, sex: Symbol('male'), jobs: function() { }, name: 'yck' }let b = JSON.parse(JSON.stringify(a))console.log(b) // {name: "yck"}
但是在通常情况下,复杂数据都是可以序列化的,所以这个函数可以解决⼤部 分问题,并且该函数是内置函数中处理深拷⻉性能最快的。当然如果你的数据中含有以上三种情况下,可以使⽤
lodash
的深拷⻉函数
转载地址:http://qnozi.baihongyu.com/