# 前端面试题及答案汇总(六) 61-70

# 第 61 题:介绍下如何实现 token 加密

  1. token加密主要是来做客户端和服务端的用户信息校验
  2. 服务端生成随机数,用户登录会将随机数告知客户端,并自己在缓存空间保留一份,每次客户端发送> token,服务端会对比缓存空间是否有此token,来判断用户是否存在
  3. 当确定token存在,进行下一步校验...,最后通过token拿取客户端需要的信息
  4. 加密方法:JWT,AES, DES... 或者直接就是随机字符串

# [第 62 题:redux 为什么要把 reducer 设计成纯函数](https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/107

redux三大原则

  • 单一数据流
  • 整个应用state都被储存在一个store里面 构成一个Object tree
  • State是只读的,唯一改变state的方法就是触发action, action是一个用于描述已发生事件的普通对象,使用纯函数来执行修改,为了描述action如何改变state tree, 你需要编写reducers

把reducer设计成纯函数,可以实现时间旅行,记录/回放或者热加载

# 第 63 题:如何设计实现无缝轮播

# 第 64 题:模拟实现一个 Promise.finally

window.Promise && !('finally' in Promise) && !function() {        
  Promise.prototype.finally = function(cb) {
    cb = typeof cb === 'function' ? cb : function() {};
      
    var Fn = this.constructor;  // 获取当前实例构造函数的引用

    // 接受状态:返回数据
    var onFulfilled = function(data) {
      return Fn.resolve(cb()).then(function() {
        return data
      })
    };

    // 拒绝状态:抛出错误
    var onRejected = function(err) {
      return Fn.resolve(cb()).then(function() {
        throw err
      })
    };

    return this.then(onFulfilled, onRejected);
  }
}();

/*********************** 测试 ***********************/
const p = new Promise((resolve, reject) => {
  console.info('starting...');

  setTimeout(() => {
    Math.random() > 0.5 ? resolve('success') : reject('fail');
  }, 1000);
});

// 正常顺序测试
p.then((data) => {
    console.log(`%c resolve: ${data}`, 'color: green')
  })
  .catch((err) => {
    console.log(`%c catch: ${err}`, 'color: red')
  })
  .finally(() => {
    console.info('finally: completed')
  });

// finally 前置测试  
p.finally(() => {
    console.info('finally: completed')
  })	
  .then((data) => {
    console.log(`%c resolve: ${data}`, 'color: green')
  })
  .catch((err) => {
    console.log(`%c catch: ${err}`, 'color: red')
  });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# 第 65 题: a.b.c.d 和 a['b']['c']['d'],哪个性能更高?

# 第 66 题:ES6 代码转成 ES5 代码的实现思路是什么

  1. 解析:解析代码字符串,生成 AST;
  2. 转换:按一定的规则转换、修改 AST;
  3. 生成:将修改后的 AST 转换成普通代码。 如果不用工具,纯人工的话,就是使用或自己写各种 polyfill 了。

# 第 67 题:数组编程题

随机生成一个长度为 10 的整数类型的数组,例如 [2, 10, 3, 4, 5, 11, 10, 11, 20],将其排列成一个新数组,要求新数组形式如下,例如 [[2, 3, 4, 5], [10, 11], [20]]。

function reflow(arr) {
  if(!arr || arr.length === 0) {
    return null;
  }
  arr.sort((a, b) => a - b);
  let res = [];
  let temp = [];
  for(let i = 0, len = arr.length; i < len; i++) {
    temp.push(arr[i]);
    if(Math.floor(arr[i + 1] / 10) !== Math.floor(arr[i] / 10)) {
      res.push(Array.from(new Set(temp)));
      temp = [];
    }
  }
  return res;
}
reflow([2, 10, 3, 4, 5, 11, 10, 11, 20])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 第 68 题: 如何解决移动端 Retina 屏 1px 像素问题

# 第 69 题: 如何把一个字符串的大小写取反(大写变小写小写变大写),例如 ’AbC' 变成 'aBc' 。

function transform(str) {
  let res = "";
  for (let i = 0, len = str.length; i < len; i++) {
    let s = str[i];
    if (s === s.toLowerCase()) {
      res += s.toUpperCase();
    } else {
      res += s.toLowerCase();
    }
  }
  console.log(res);
  return res;
}
const str = "aBcFG";
transform(str);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 第 70 题: 介绍下 webpack 热更新原理,是如何做到在不刷新浏览器的前提下更新页面的

参考