蚂蚁前端一面(2022.3.4)

239 阅读8分钟

投递信息

面试问题

  1. 小程序和普通web的渲染区别?

    小程序两个线程执行是异步的,没有存在互斥关系;而普通web的js引擎线程和GUI渲染线程互斥

  2. 为什么小程序的白屏时间比web端短?

    主要是因为: “微信 Web 资源离线存储”

    微信 Web 资源离线存储是面向 Web 开发者提供的基于微信内的 Web 加速方案。

    通过使用微信离线存储,Web 开发者可借助微信提供的资源存储能力,直接从微信本地加载 Web 资源而不需要再从服务端拉取,从而减少网页加载时间,为微信用户提供更优质的网页浏览体验。每个公众号下所有 Web App 累计最多可缓存 5M 的资源。

    当小程序没网或者网络环境差时, 通过微信Web资源离线存储技术, 可以直接打开对于小程序首页

    当浏览器没网时,直接显示“未连接到互联网”’; 当网络环境差时(自己设置网络速度), 会出现长时间的白屏, 即使资源都在 disk cache 或者 memory cache 中.

    参考: 小程序简介 | 微信开放文档

  3. 小程序渲染和Web渲染哪个性能更优? 为什么? (渲染和上面的白屏有关联,但是是两个不同的问题)

    • Web采用单页面实例,小程序采用多WebView实例,因此其更轻便,渲染性能更佳;
    • Web的JS逻辑层和视图层混合在一起,比较重,且相对而言可维护性比较低。小程序其视图层和逻辑层分别独立,代码更具备可维护性,且不会和JS共用一个Context,不会存在页面渲染逻辑和JS逻辑相互阻塞的情况。

    参考: 04-大前端底层原理|小程序框架渲染原理 - 掘金

  4. 渲染界面技术你了解多少?

    参考: 渲染技术总结

  5. 小程序如何优化首屏渲染?

    参考: 小程序首屏渲染优化

  6. Web缓存你知道哪些?

    参考: Web缓存分类

  7. 市面上这么多小程序组件库,为什么还要再自己开发一个? (简历中项目相关问题)

    1. 自学练手
    2. 其次我开发的组件更多是添加动效的一些有意思的组件,而非button这样的常规组件 欢迎试玩: github.com/lizhuang-zh…
  8. 设计一个好的组件,需要考虑的因素有哪些?

    1. 将更多的设置交由开发者进行设定
    2. 松耦合(组件可以独立运行)
    3. 辅助代码的分离(一些公用工具类的分离)

参考: [译] 前端组件设计原则 - 掘金

  1. 堆和栈有什么区别? 堆的数据结构长什么样子?

    堆和栈的区别是什么

    1. 堆栈空间分配区别 (栈由操作系统(编译器)自动分配释放; 堆一般由程序员分配释放)
    2. 堆栈缓存方式区别 (栈使用的是一级缓存, 它们通常都是被调用时处于存储空间中,调用完毕立即释放。堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。)
    3. 堆栈数据结构区别 (堆可以被看成是一棵树(完全二叉树),如:堆排序。而栈是一种先进后出的数据结构。)

参考: 堆和栈的区别有哪些-常见问题-PHP中文网

堆这种数据结构本质是一个完全二叉树, 完全二叉树的形式是指除了最后一层之外,其他所有层的结点都是满的,而最后一层的所有结点都靠左边.

  1. TCP和UDP区别?

    1. TCP面向连接,UDP无连接
    2. TCP提供可靠的服务
    3. TCP面向字节流,UDP面向报文
    4. TCP是1对1,而UDP1对1或者1对多
    5. TCP首部较大20字节,UDP首部8个字节
  2. 聊天的网络协议用什么?

    WebSocket,因为WebSocket相比与http(这里的http指的是http1.0以及之前的版本)可以建立一个持久连接,并且可以由服务器主动发送请求

  3. WebSocket基于TCP还是UDP?

    TCP (但是我当时答的UDP,还一本正经的扯为什么是UDP)

    它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

    其他特点包括:

    (1)建立在 TCP 协议之上,服务器端的实现比较容易。

    (2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

    (3)数据格式比较轻量,性能开销小,通信高效。

    (4)可以发送文本,也可以发送二进制数据。

    (5)没有同源限制,客户端可以与任意服务器通信。

    (6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

    ws://example.com:80/some/path
    

  4. HTTP1.1和HTTP2有什么区别?

HTTP1.1存在问题(HTTP2.0提供解决方式):

  1. 队头阻塞 (多路复用解决)

  2. 头部未压缩和头部冗余 (利用HPACK算法,共同维护一个字典)

  3. 只能客户端请求 (服务端可推送)

  4. 没有控制请求优先级 (数据流: 每个请求或响应的所有数据包,称为⼀个数据流( Stream )。每个数据流都标记着⼀个独⼀⽆⼆的编号. 客户端通过编号可设置请求优先级, 让服务器对其进行优先处理) 其次, http2.0增加二进制分帧层,提高编码效率

  5. 除开 Cookie、LocalStorage、SessionStorage 这些存储方式,前端还有哪些存储方式?

    1. Web SQL
    2. IndexedDB
  6. Cookie、LocalStorage、SessionStorage的区别?

  7. js中的0.1 + 0.2等于0.3吗? 为什么?

    运算步骤:

    1. 将 0.1和 0.2 转为二进制数(无限循环小数)
    2. 将一般二进制形式转换为指数形式
    3. 将指数形式转换成IEEE754标准

    1. 将 0.1 和 0.2 做加法运算

    2. 将 0.1 + 0.2 的结果转换为十进制

function calcul(str) {
    let sum = 0;
    for(let i = 0; i < str.length; i++) {
        let acc = parseFloat(str[i]) * Math.pow(2, -(i + 1));
        sum += acc;
    }
    return sum;
}

let res = calcul('0100110011001100110011001100110011001100110011001100111');
console.log(res);  // 0.30000000000000004

简单的说: 造成这个现象的原因是因为二进制的 0.1 是一个无限循环小数, 计算机无法精确表示,从而丢失精度,也就造就这样的现象

参考:

www.bilibili.com/video/BV1RE…

www.bilibili.com/video/BV1xq…

  1. 实现一个方法, 让0.1 + 0.2 == 0.3 ?

    // 方式一
    function foo1(n1, n2) {
    let arr1 = n1.toString().split('.');
    let arr2 = n2.toString().split('.');
    let result = parseInt(arr1[1]) + parseInt(arr2[1]);
    return Number(arr1[0] + '.' + result);
    }
    // 方式二
    function foo2(n1, n2) {
    let result = n1 * 10 + n2 * 10;
    return result / 10;
    }
    
    let res1 = foo1(0.1, 0.2);
    let res2 = foo2(0.1, 0.2);
    console.log(res1);   // 0.3
    console.log(res2);   // 0.3
    
  2. CSS Modules 听说过吗?

    本文介绍的 CSS Modules 有所不同。它不是将 CSS 改造成编程语言,而是功能很单纯,只加入了局部作用域和模块依赖,这恰恰是网页组件最急需的功能。

    css modules作用

    1. 局部作用域: 通过哈希生成独一无二的class名, 来产生局部作用域
    2. 全局作用域: CSS Modules 允许使用:global(.className)的语法,声明一个全局规则。凡是这样声明的class,都不会被编译成哈希字符串
    3. 定制哈希类名: css-loader默认的哈希算法是[hash:base64],这会将.title编译成._3zyde4l1yATCOkgn-DBWEL这样的字符串
    4. Class 的组合: 在 CSS Modules 中,一个选择器可以继承另一个选择器的规则,这称为"组合"
    5. 输入输出模块: 选择器也可以继承其他CSS文件里面的规则。
    6. 输入变量: CSS Modules 支持使用变量,不过需要安装 PostCSS 和 postcss-modules-values。

css modules优势

  • 解决全局命名冲突问题 css modules只关心组件本身命名唯一
  • 模块化 可以使用composes来引入自身模块中的样式以及另一个模块的样式
  • 解决嵌套层次过深的问题 使用扁平化的类名

参考:

css modules是什么? - 前端一点红 - 博客园

CSS Modules 用法教程 - 阮一峰的网络日志

  1. Vue中Scoped原理? 什么情况下用Scoped? 在全局 scoped 中,如何修改深层组件的样式?

    使用场景

    Vue组件内样式局部化

    原理

    加入scoped, 就会在节点上添加自定义属性: data-v-xxx

    通过CSS选择器中的属性选择器最终添加样式

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>属性选择器的设置</title>
    <style>
      /* 这样设置两个div都是红色 */
      /* .main {
          width: 100px;
          height: 100px;
          background-color: red;
      } */
    
      /* 
          利用属性选择器 
            - 第一个div绿色
            - 第二个div蓝色
      */
      .main[data-v-abc] {
          width: 100px;
          height: 100px;
          background-color: green;
      }
      .main[data-v-123] {
          width: 100px;
          height: 100px;
          background-color: blue;
      }
    </style>
    </head>
    <body>
    
        <div class="main" data-v-abc>111</div>
        <br>
        <div class="main" data-v-123>222</div>
    
    </body>
    </html>
    

    在全局 scoped 中,修改深层组件的样式(样式穿透)

    app.vue

    <template>
        <div id="app">
            <div class="main">我是App.vue部分</div>
            <div class="comp">
                <hello-world />
            </div>
        </div>
    </template>
    
    <script>
    import HelloWorld from "./components/HelloWorld.vue";
    
    export default {
      name: "App",
      components: {
          HelloWorld,
      },
    };
    </script>
    
    <style scoped>
    .main {
        width: 200px;
        height: 200px;
        background: red;
    }
    
    /* 
    样式穿透
    */
    /* stylus的样式穿透 */
    .comp >>> .main {
        border: 13px solid goldenrod;
    }
    /* 通用样式穿透 */
    /* ::v-deep .comp .main {
        border: 13px solid goldenrod;
    } */
    
    /* 无法穿透到组件中 */
    /* .comp .main{
        border: 13px solid goldenrod;
    } */
    </style>
    

    HelloWorld.vue

    <template>
        <div>
            <div class="main">这是HelloWorld组件</div>
        </div>
    </template>
    
    <script>
    export default {
        name: "HelloWorld",
        props: {},
    };
    </script>
    
    <style scoped>
    .main {
        width: 100px;
        height: 100px;
        background: blue;
    }
    </style>
    

    参考:

    www.bilibili.com/video/BV1dQ…

    vue样式穿透 - 认真,是一种态度 - 博客园

  2. 能说下SPA单页应用?

总结评价

面试官最后打分: 80(通过)

面试官点评: 前端的知识面不广, 需要补强.还有其实就是服务层,前端同学别把自己定义为一个开发UI的去了,把自己尽可能作为一个Web大前端 (包括后端方面的相关内容)