博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS面试题汇总(三)
阅读量:3958 次
发布时间:2019-05-24

本文共 3741 字,大约阅读时间需要 12 分钟。

1.generator 原理

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(); } } }); }

2. Promise

  • PromiseES6 新增的语法,解决了回调地狱的问题
  • 可以把 Promise 看成⼀个状态机。初始是 pending 状态,可以通过函数 resolvereject ,将状态转变为 resolved或者 rejected 状态,状态⼀旦改变就不能再次变 化。
  • then 函数会返回⼀个 Promise 实例,并且该返回值是⼀个新的实例⽽不是之前的实 例。因为Promise 规范规定除了pending 状态,其他状态是不可以改变的,如果返回 的是⼀个相同实例的话多个 then 调⽤就失去意义了。 对于 then来说,本质上可以 把它看成是flatMap

3.== 和 ===区别,什么情况⽤ ==

这⾥来解析⼀道题⽬ [] == ![] // -> true ,下⾯是这个表达式为何为true 的步骤

// [] 转成 true,然后取反变成 false[] == false// 根据第 8 条得出 [] == ToNumber(false) [] == 0// 根据第 10 条得出ToPrimitive([]) == 0// [].toString() -> '''' == 0// 根据第 6 条得出 0 == 0 // -> true

=== ⽤于判断两者类型和值是否相同。 在开发中,对于后端返回的 code , 可以通过 == 去判断

4. 基本数据类型和引⽤类型在存储上的差别

前者存储在栈上,后者存储在堆上

5. setTimeout 倒计时误差

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)

6.数组降维

[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]])

7.深拷⻉

这个问题通常可以通过 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/

你可能感兴趣的文章
cookie、session、sessionid 与jsessionid[转]
查看>>
常见Oracle HINT的用法
查看>>
JAVA中各类CACHE机制实现的比较 [转]
查看>>
PL/SQL Developer技巧
查看>>
3-python之PyCharm如何新建项目
查看>>
15-python之while循环嵌套应用场景
查看>>
17-python之for循环
查看>>
18-python之while循环,for循环与else的配合
查看>>
19-python之字符串简单介绍
查看>>
20-python之切片详细介绍
查看>>
P24-c++类继承-01详细的例子演示继承的好处
查看>>
P8-c++对象和类-01默认构造函数详解
查看>>
P1-c++函数详解-01函数的默认参数
查看>>
P3-c++函数详解-03函数模板详细介绍
查看>>
P4-c++函数详解-04函数重载,函数模板和函数模板重载,编译器选择使用哪个函数版本?
查看>>
P5-c++内存模型和名称空间-01头文件相关
查看>>
P6-c++内存模型和名称空间-02存储连续性、作用域和链接性
查看>>
P9-c++对象和类-02构造函数和析构函数总结
查看>>
P10-c++对象和类-03this指针详细介绍,详细的例子演示
查看>>
bat备份数据库
查看>>