前端面试重要问题总结(前端100问小结)(七)

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

题目讨论
jwt举例

需要一个secret(随机数)
后端利用secret和加密算法(如:HMAC-SHA256)对payload(如账号密码)生成一个字符串(token),返回前端
前端每次request在header中带上token
后端用同样的算法解密

第 62 题:redux 为什么要把 reducer 设计成纯函数

题目讨论
redux三大原则

单一数据流
整个应用state都被储存在一个store里面 构成一个Object tree
State是只读的
唯一改变state的方法就是触发action, action是一个用于描述已发生事件的普通对象
使用纯函数来执行修改
为了描述action如何改变state tree, 你需要编写reducers
把reducer设计成纯函数,可以实现时间旅行,记录/回放或者热加载

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

题目讨论
这里说一个不需要clone的方案:

<div class="slide">
  <ul>
    <li>图片1</li>
    <li>图片2</li>
   <li>图片3</li>
  </ul>
</div>

1、最外层div.slide定宽、相对定位relative

2、ul 足够宽,最起码li数*li宽度,这里有个技巧,直接 width: 9999em,目的是让里面的所有li一字排开

3、滚动效果通过控制ul的left或者transform来进行滚动效果

4、到了最后一个li,往后看第一个li的时:

  • 4.1、准备继续滚动,把最后一个的li设置为相对定位relative,left值为此时此刻相对ul的位置(设置的时候不要带缓动效果),目的是让最后一个li不动。
  • 4.2、然后把ul的left或者transform设为0(这步没有缓动效果),
  • 4.3、然后再正常的开始一样出现第一个li的滚动效果(这步有缓动效果)
  • 4.4、最后等无缝的第一个li效果完成后,把最后一个li的left值复原为0

5、到第一个li,往前看最后一个li时,也是和上面同理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>轮播</title>
    <style>
        *{
            padding: 0;
            margin: 0;
            list-style: none;
        }
        #continer{
            width: 300px;
            height: 200px;
            position: relative;
            margin: 20px auto;
            border: 1px solid;
            overflow: hidden;
        }
        #lunbo{
            width: 9999em;
            height: 100%;
            position: absolute;
            top: 0;
            left: 0;
        }
        li{
            float: left;
            width: 300px;
            height: 200px;
            text-align: center;
            line-height: 200px;
            color: brown;
            font-size: 30px;
        }
    </style>
</head>
<body>
    <div id="continer">
        <ul class="ul" id="lunbo">
            <li class="list">1</li>
            <li class="list">2</li>
            <li class="list">3</li>
            <li class="list">4</li>
            <li class="list">5</li> 
        </ul>
    </div>
</body>
<script src="./js/jquery3.0.min.js"></script>
<script>
    let selectNum = 0
    function lunboFun (selectNum, time) {
        $('#lunbo').animate({
            'left': -1 * selectNum * 300
        }, time, () => {
            selectNum++
            setTimeout(() => {
                if (selectNum > 4) {
                    selectNum = 0
                    $('ul li:last').css({
                        'position': 'absolute'
                    }, 0)
                    $('ul li:last').animate({
                        'left': -300
                    }, 0)
                    $('#lunbo').animate({
                        'left': 300
                    }, 0)
                } else if (selectNum <3) {
                    $('ul li:last').css({
                        'position': 'relative',
                        'left': 0
                    }, 0)
                }
                lunboFun(selectNum, 1000)
            }, 2000)
        });
    }
    lunboFun(selectNum, 1000)

</script>
</html>

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

题目讨论

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

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

题目讨论
应该是 a.b.c.d 比 a[‘b’][‘c’][‘d’] 性能高点,后者还要考虑 [ ] 中是变量的情况,再者,从两种形式的结构来看,显然编译器解析前者要比后者容易些,自然也就快一点。
下图是两者的 AST 对比:
在这里插入图片描述

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

题目讨论
把 ES6 代码转成 ES5 代码的实现思路可以分成三步:

打开冰箱
把大象装进去
关上冰箱
喔,不对,原谅我开了个玩笑,嗯,有点冷……

将ES6的代码转换为AST语法树,然后再将ES6 AST转为ES5 AST,再将AST转为代码

回到正题上来,说到 ES6 代码转成 ES5 代码,我们肯定会想到 Babel。所以,我们可以参考 Babel 的实现方式。

那么 Babel 是如何把 ES6 转成 ES5 呢,其大致分为三步:

将代码字符串解析成抽象语法树,即所谓的 AST
对 AST 进行处理,在这个阶段可以对 ES6 代码进行相应转换,即转成 ES5 代码
根据处理后的 AST 再生成代码字符串
基于此,其实我们自己就可以实现一个简单的“编译器”,用于把 ES6 代码转成 ES5。

比如,可以使用 @babel/parser 的 parse 方法,将代码字符串解析成 AST;使用 @babel/core 的 transformFromAstSync 方法,对 AST 进行处理,将其转成 ES5 并生成相应的代码字符串;过程中,可能还需要使用 @babel/traverse 来获取依赖文件等。

第 67 题:数组编程题

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

// 得到一个两数之间的随机整数,包括两个数在内
function getRandomIntInclusive(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 
}
// 随机生成10个整数数组, 排序, 去重
let initArr = Array.from({ length: 10 }, (v) => { return getRandomIntInclusive(0, 99) });
initArr.sort((a,b) => { return a - b });
initArr = [...(new Set(initArr))];

// 放入hash表
let obj = {};
initArr.map((i) => {
    const intNum = Math.floor(i/10);
    if (!obj[intNum]) obj[intNum] = [];
    obj[intNum].push(i);
})

// 输出结果
const resArr = [];
for(let i in obj) {
    resArr.push(obj[i]);
}
console.log(resArr);

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

题目讨论
造成边框变粗的原因
其实这个原因很简单,因为css中的1px并不等于移动设备的1px,这些由于不同的手机有不同的像素密度。在window对象中有一个devicePixelRatio属性,他可以反应css中的像素与设备的像素比。

devicePixelRatio的官方的定义为:设备物理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素。

具体解决方法

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

function processString (s) {
    var arr = s.split('');
    var new_arr = arr.map((item) => {
        return item === item.toUpperCase() ? item.toLowerCase() : item.toUpperCase();
    });
    return new_arr.join('');
}
console.log(processString('AbC'));

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

题目讨论
1.当修改了一个或多个文件;
2.文件系统接收更改并通知webpack;
3.webpack重新编译构建一个或多个模块,并通知HMR服务器进行更新;
4.HMR Server 使用webSocket通知HMR runtime 需要更新,HMR运行时通过HTTP请求更新jsonp;
5.HMR运行时替换更新中的模块,如果确定这些模块无法更新,则触发整个页面刷新。

简单来说就是:hot-module-replacement-plugin 包给 webpack-dev-server 提供了热更新的能力,它们两者是结合使用的,单独写两个包也是出于功能的解耦来考虑的。
1)webpack-dev-server(WDS)的功能提供 bundle server的能力,就是生成的 bundle.js 文件可以通过 localhost://xxx 的方式去访问,另外 WDS 也提供 livereload(浏览器的自动刷新)。
2)hot-module-replacement-plugin 的作用是提供 HMR 的 runtime,并且将 runtime 注入到 bundle.js 代码里面去。一旦磁盘里面的文件修改,那么 HMR server 会将有修改的 js module 信息发送给 HMR runtime,然后 HMR runtime 去局部更新页面的代码。因此这种方式可以不用刷新浏览器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值