0%

T5 and mT5

What is mT5?: mT5 is multilingual variant of T5 that was pre-trained on a dataset with 101 languages.

What is T5?: T5 model proposed a unified “text-to-text” format for all text-based NLP tasks. For example, for categorizing tasks, QA tasks, and translation tasks used different models architectures and output formats. The T5 unifies them into “Input Text -> Output Text” format that only pure text is involved.

  • T5 uses a basic encoder-decoder Transformer architecture and is pre-trained on a masked language modeling “span-corruption” objective.

Span Corruption: randomly erase some of the segments of input text and masked with special marks. The model should learn to recover the original input text.

  • mT5 solve bias and overfit/underfit problems on different language by boosting lower resources languages.

G2P-DDM

G2P-DDM: Generating Sign Pose Sequence from Gloss Sequence with Discrete Diffusion Model

Sign Language Production(SLP): automatically translate spoken languages into sign sequences.

G2P-DDM mainly focus on the transformation of sign gloss sequences into their corresponding sign pose sequences (G2P).

Novel Methods: convert the continuous pose space generation problem into a discrete sequence generation problem.

Three steps approach:

  • Pose-VQVAE: quantalized a 3D skeleton sequence into token. Seperate the skeleton into body, left hand, and right hand with independent codebook.
  • G2P-DDM + CodeUnet: conduct mask-and-replace discrete diffusion on discrete latent, reconstruct with U-net + Transformer based on temporal and spatial features.
  • Sequential-KNN: non-autoregressive needs a target length, using the semantic similarity of token to do kNN-based density peaks clustering algorithm, to get corresponding frame length of each gloss, predict the total length when inferencing.

Pose VQ-VAE

Discretize Pose Latent Space

Encoder and Separating Skeleton

Input N frames, J nodes, and K dimension feature sequence. Separating the skeleton into three subsequences: pose, left hand, and right hand. Each of them will pass its own linear layers, concatenation layer and spatial-temporal Transformer to learn the long-term dependence and obtain feature codes.

Multi-codebook Quantalization

Quantalize the feature codes of each frame by nearest neighbour method into three independent codebooks (pose, left hand, and right hand). Size of each code is V, obtaining a discrete token embedding (quantalized features).

Decode and SPL (Structure Prediction Layer)

Decoder also adopts the spatial-temporal Transformer architecture, the output features are also separated according to the three subsequences, then reconstruct the key node sequence via SPL. SPL will model the dependency of human body key nodes.

End-to-End Training

The loss of Pose-VQVAE contains the reconstruction of three patches and the standard codebook with stop gradient.

Discrere Diffusion

Modeling in discrete latent space.

Forward Fusion Markov Chain

Fuse the discrete codebook indexes into pure noise.

Length-varied mask-and-Replace Expansion

Standard dicrete diffusion often is length-fixed, to address this G2P-DDM intruduces: - Length Predictor: predict the length of each gloss and aggregate to get total length. - Introduce [MASK]/[PAD] marks into discrete diffusion. Alternate the diffusion process into recovering from [MASK]/[PAD] marks.

CodeUnet

CodeUnet is mixed with Transformer the the downsample/upsamle of Unet.

  • Middle Modules: a Transformer Encoder and Decoder, Encdoer (6 layers) read the conditional features get from the gloss, decoder(2 layers) conduct self-attention and cross-attention from sequence features to gloss, and use AdaLN to mix the time step.
  • Contract/Expand Route (U-shaped): 2 Transformer Encoder for each layer.

Pipeline Summary

  • Input/Output
    • Input: gloss sequence (discrete token sequence)
    • Output: skeleton sequence
  • Pose Discretazation
    • Separate Skeleton: separate the skeleton of each fram into pose/left hand/right hand.
    • Three patches -> linear layer -> spatial-temporal Transformer -> frame latent vector
    • Three patches lookup each codebook nearest neighbour -> get token
    • token -> codebook vector -> spatial-temporal Transformer + SPL -> skeleton reconstrcution
  • Generative Model
    • Length Prediction
      • use Sequential-KNN + Categorizer to predict the frame number of each gloss.
      • Get target token sequence total length N.
    • Initialize Diffusion
      • Construct a [MASK]/[PAD] sequence of length N.
    • Discrete Diffusion
      • Forward: randomly substitute with MASK/PAD when training.
      • Backward: erase noise using CodeUnet.
      • Condition: gloss token (Transformer Encoder) -> cross attention injected with CodeUnet.
      • Time: diffusion step t is injected via AdaLN
  • Skeleton Reconstruction
    • Input the generated token sequence into Pose-VQVAE decoder.
    • Get sequential 3D skeleton sequence.

Summary:

gloss -> length prediction -> discrete diffusion: obtain codebook token sequence -> Pose-VQVAE decode -> skeleton sequence.

推荐系统架构

推荐和搜索的核心任务是从海量物品中找到用户感兴趣的内容。

系统架构

一般推荐系统架构分为离线层(Offline)、近线层(Nearline)和在线层(Online)。

  • 离线层:不实用实时数据,不提供实时响应。
    • 数据处理、数据存储。
    • 特征工程、离线特征计算。
    • 离线模型训练。
    • 优势与不足:数据量级最大,需要存储海量数据、大规模特征工程以及多机分布式模型训练。当前主流通过HDFS收集业务数据,通过Hive等大数据工具进行数据提取、筛选以及处理。主流框架是Spark。可以进行批量处理与计算而没有响应时间的要求。
  • 近线层:使用实时数据,不保证实时响应。
    • 不严格要求实时性,但需要弥补离线层与在线层之间的不足。适合处理对时延较为敏感的任务。
      • 特征的事实更新计算:离线层数据与实时数据分布不一致,通过近线层调节。
      • 获取实时训练数据:用户较短时间内产生的数据特征可以通过近线层直接输入模型。
      • 模型实时训练:通过在线学习的方法更新推送模型。
    • 主流大数据框架:Flink,Storm。
    • 架构技术栈
  • 在线层:使用实时数据,保证实时在线服务。
    • 面向用户的一层,对响应时延有要求,需要立即响应推荐结果。
      • 模型在线服务:包括了快速召回和排序。
      • 在线特征快速处理拼接:根据传入的用户ID和场景,快速读取特征和处理。
      • AB实验或分流:根据不同用户采用不一样的模型,比如冷启动用户和正常服务模型。
      • 运筹优化和业务干预:比如对特殊商家的流量扶持、对特定内容的限流。

算法架构

推荐系统会细分为四个阶段:召回、粗排、精排、重排.

  • 召回:从推荐池中选取大量items送个后续排序模块。
    • 由于面对的候选集庞大且需要在线输出,所以召回模块需要轻量快速低延迟。不需要十分准确,但不可遗漏。
    • 考虑内容:
      • 用户层面:用户需求、兴趣与场景多元化。
      • 系统层面:增强鲁棒性。兜底。
      • 多样性内容分发:召回目标多元。
      • 可解释性。
  • 粗排:对召回结果进行初步筛选送给精排。兼顾准确性和低延迟。
    • 考虑内容:
      • 根据精排模型的重要特征来做候选集的截断。
      • 根据与user相关性进行召回结果截断。
      • 性能保证。
  • 精排:大部分算法研究的层面。对粗排的候选集进行打分和排序。
  • 重排:解决精排结果可能同质化和冗余的问题。以及根据运营策略等去影响精排结果。是对精排结果的微调。

技术栈

画像层

推荐系统的物料库,绘制用户、商品画像等。通过tag的方式进行统计。

  • 内容特征提取与标签分类
    • 文本理解:RNN,TextCNN,FastText,Bert等。
    • 关键词标签:TF-IDF,Bert,LSTM-CRF。
    • 内容理解:TSN,RetinaFace,PSENet等。
    • 知识图谱:KGAT,RippleNet。

召回/粗排

经典模型召回:FM,双塔DSSM,Multi-View DNN等。 序列模型召回:CBOW,Skip-Gram,GRU,Bert等。 用户序列拆分:对用户的多维兴趣进行拆分,刻画更细致的方向。 知识图谱:对推荐结果的可解释性。 图模型:通过图模型来表示系统。

精排

研究最多的方向,主要通过各种深度学习方法进行打分排序。

  1. SFT Loss计算方法
    • 交叉熵损失 CE Loss
      • 假设输入prompt为x,目标输出序列为 y = (y1, y2, ..., yT),模型预测条件概率为 pθ(yt|x, y < t)
      • 则SFT Loss定义为: SFTθ = −∑t = 1Tlog pθ(yt|x, y < t)
    • 模型在生成每一个token时会预测一个概率分布,而希望它尽可能把正确token的概率提高。其损失就是“模型预测分布和参考答案之间的差距”。
    • 每一步预测都会对计算交叉熵取平均,最后对整个结果取平均。
    • 交叉熵:用来度量两个概率分布差异的函数,熵越小越接近真实分布。
    • 真实分布p(x),预测分布q(x),交叉熵定义为 H(p, q) = −∑p(xi)log q(xi).
  2. Transformer与注意力机制
    • Attention类别:Self Attention,Cross Attention,MHA,Flash Attention等。
    • Transformer结构:
      • Encoder模块:由N层堆叠,每一层主要包含:
        • 多头自注意力:捕捉输入序列中不同位置之间的依赖关系。
          • Attention(Q, K, V) = softmax(QKT/sqrtdk)V
          • 其中 Q, K, V 均由输入 X 投影得到:Q = XWQ, K = XWK, V = XWV.
        • 前向传播:对于每个token进行线性变换,提高表达能力.
          • FFN(x) = ReLU(xW1 + b1)W2 + b2
        • 残差连接和Layer Norm:保证梯度稳定,提高训练效果。
          • X = LayerNorm(X + MultiHead(X, X, X)), Y = LayerNorm(X + FFN(X))
      • Decoder模块:同样由N层堆叠
        • Masked多头自注意力:防止token看到未来信息,保证自回归生成。
          • QKT + M,通过mask矩阵屏蔽token之后的所有位置。
        • Encoder-Decoder多头注意力:让Decoder关注Encoder计算出的特征。
          • 公式相同,但是Q由decoder产生,K和V由Encoder提供。
        • 前馈网络:增强表达。
        • 残差连接:稳定训练,提高梯度传播能力。
        • Decoder的最终输出会通过一个线性变换和softmax层得到最后的预测分布。
    • 使用多头自注意力机制的优势:
      • MHA可以让模型从不同的表示子空间中学习不同的特征,增强模型的表达能力;提高模型的鲁棒性,减少单个注意力头可能带来的信息丢失;允许不同的注意力头关注输入序列的不同部分,使模型能够捕捉更丰富的上下文信息;增强模型的表达能力,避免单一注意力模式可能导致的局部最优解。
    • 为什么Q和K需要使用不同的权重矩阵:如果Q和K使用相同的权重矩阵,则 QKT 变成了一个对称矩阵,这样会导致注意力分数的计算缺乏灵活性,无法区分不同的输入关系。
    • 计算注意力使用点积计算的优势:
      • 计算效率更高,矩阵运算可以使用并行加速;避免了额外的可训练参数,而假发注意力需要额外的权重矩阵和非线性变换;也适用于高维向量。
    • 为什么对 QKT 进行scaled处理:
      • dk 是K的维度,如不不进行缩放,当 dk 较大时 QKT 的数值会变得过大,导致softmax的梯度消失。scaled后可以使得分布更加平稳,提高训练稳定性。
    • 为什么在进行多头注意力时需要先concat再降维:
      • 如果不降维会导致每个头的计算量变得很大,因此一般将d维的输入向量映射到一个较低维的子空间,使得每个头的计算量减少;如果直接相加那么所有注意力头的输出都会累驾到同一个维度上;而多头的优势在于可以关注不同的特征,直接相加会让这些特征混合,进而无法区分不同的注意力模式,降低了表达力。
    • Mask如何实现:对于需要padding的位置设置负无穷,需要的位置设置0.
    • 残差连接的作用:
      • 缓解梯度消失:梯度可以残差路径传播,使得深层网络训练更加稳定。
      • 加速收敛:通过跳跃连接使得梯度流动更加顺畅,减少训练时间。
      • 防止信息丢失:输入信息可以沿着残差路径流向更深层网络。
      • 提高泛化能力:残差+LayerNorm可以防止过拟合。
    • 为什么用LayerNorm而不是BatchNorm:
      • BatchNorm依赖于mini-batch统计量,而NLP任务序列长度不固定,BatchNorm可能表现不稳定,而LayerNorm不受影响。BatchNorm也依赖于较大的batchsize来获得稳定的均值和方差,而Transformer的batchsize通常较小。此外,transformer中每个token的计算是独立的,LayerNorm可以为每个token进行归一化,而batchnorm需要整个batch的信息。

  1. Echarts
    • 是一个基于 JavaScript 的开源数据可视化工具库,用来绘制交互式、可定制的图表。
    • 常用的组件:
      • title标题组件:show,text,link等属性。
      • toolbox工具栏组件:导出图片、数据视图、切换、缩放
      • tooltip组件:trigger组件
      • markPoint标注点
      • markLine图标标线
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        var chart = echarts.init(document.getElementById('main'));

        // 2. 配置项
        var option = {
        title: { text: 'ECharts 示例' },
        tooltip: {},
        legend: { data:['销量'] },
        xAxis: { data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"] },
        yAxis: {},
        series: [{
        name: '销量',
        type: 'bar', // 柱状图
        data: [5, 20, 36, 10, 10, 20]
        }]
        };

        // 3. 使用配置项生成图表
        chart.setOption(option);
  2. Webpack
    • webpack 是一个 前端资源打包工具 (module bundler),本质作用就是:把你写的各种资源(JS、CSS、图片、字体等),当作模块来处理,经过编译打包生成浏览器可用的优化文件。
    • 在前端项目中如果用到ES6+、Vue/React组件化、TypeScript、各种资源(图片、字体等)需要用到webpack把它们转换成浏览器能认识的纯JS/CSS/HTML文件
    • 打包过程:
      • 从入口文件开始,构建依赖关系图。
      • 遇到 import 或 require,就递归分析依赖。
      • 通过 Loader 转换代码。
      • 把所有模块打包成一个或多个 bundle。
      • 插件做额外优化(压缩、抽离 CSS、生成 HTML)。
    • Module、Chunk与Bundle的关系:
      • Module:项目中所有的源码文件都叫模块。可以是 JS、CSS、图片、字体等,webpack把它们都视作“模块”。
      • Chunk:webpack在打包过程中,按照依赖关系,把多个module合并成一个“代码块”。
      • Bundle:chunk经过webpack处理、loader转换、插件优化后,最终生成的实际输出文件。
    • Bibel转译器
      • 将高版本语言(ES6+等)转译成兼容性更好的旧版本JS,是一个JS编译器。
      • 原理:
        • 解析(Parsing):源代码转译为抽象语法树。
        • 转换(Transform):遍历AST,调用各种插件修改节点。
        • 生成(Generating):把修改后的 AST 再转成代码字符串。
    • Webpack打包和不打包区别:
      • 运行效率:若不打包,写的代码较多需要发送多次http请求,不易维护。
      • 对技术的支持:对于高版本语法可以通过webpack的bable来转化,使得低版本浏览器可以运行。
  3. HTTP协议版本对比
    • HTTP/1.0:每次请求都新建连接,效率最低。
    • HTTP/1.1:支持长连接,但有队头阻塞。
    • HTTP/2:二进制、多路复用、头部压缩,但仍受 TCP 队头阻塞限制。
    • HTTP/3:基于 QUIC(UDP),真正解决队头阻塞,握手更快,更适合移动互联网。
    • HTTP Versions
  4. HTTP与HTTPS
    • HTTPS (HTTP Secure) = HTTP + SSL/TLS。有身份验证。
    • 对比:
      • 端口:HTTP用80,HTTPS用443.
      • 安全性:HTTP明文传输,HTTPS加密传输。
      • 速度:HTTP相对较快。
      • 成本:HTTPS需要SSL/TLS证书。
  5. OSI七层网络模型
    1. 应用层:面向用户,有HTTP,FTP,SMTP,DNS等协议。
    2. 表示层:负责数据加密、压缩、表示等,把应用层数据转换为标准格式。如SSL/TLS,JPEG/MP3等。
    3. 会话层:负责建立、终止和管理会话。
    4. 传输层:提供端到端数据传输,保证数据可靠性。使用TCP/UDP。
    5. 网络层:负责路由寻址(IP),使用IP/ICMP/BGP等算法和协议。
    6. 链路层:在同一局域网内传输数据帧,解决错误检测,错误重传等。通过Ethernet,MAC地址等寻址。在交换机层面沟通。
    7. 物理层:比特流传输。

高频手撕代码考察

  1. 手写Promise.all()

    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
    //接受一个数据(或可迭代对象)
    //等所有 Promise 成功,返回一个新 Promise,结果是 按顺序 的结果数组。
    //如果其中有一个失败(reject),立即返回 reject。
    function promiseAll(promises) {
    return new Promise((resolve, reject) => {
    if (!Array.isArray(promises)) {
    return reject(new TypeError("args not an array"));
    }

    let results = [];
    let completed = 0;

    promises.forEach((p, index) => {
    Promise.resolve(p).then(value => {
    results[index] = value;
    completed++;
    if (completed === promises.length) {
    resolve(results);
    }
    }) catch (error => {
    reject(error);
    });
    });

    if (promises.length === 0) {
    resolve([]);
    }
    });
    }

    const p1 = Promise.resolve(1);
    const p2 = new Promise(res => setTimeout(() => res(2), 1000));
    const p3 = 3;

    promiseAll([p1, p2, p3])
    .then(results => console.log("success:", results))
    .catch(error => console.error("failed:", error));

  2. 手撕防抖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    function debounce(fn, delay) {
    let timer = null;

    return function(...args) {
    const context = this;
    if(timer) {
    clearTimeout(timer);
    }

    timer = setTimeout(() => {
    fn.apply(context, args);
    }, delay);
    };
    }

    function onResize() {
    console.log("resize 事件触发:", new Date().toLocaleTimeString());
    }
    // 500ms 防抖
    window.addEventListener("resize", debounce(onResize, 500));

  • 在防抖函数里:
    • context = this; 保存了外部调用时的 this(比如某个按钮 DOM 对象)。
    • args = arguments(用扩展语法 …args 收集)保存了调用时传进来的参数。
  • 当定时器触发时,如果直接写 fn():
    • this 会丢失(定时器里的 this 默认是 window 或 undefined)。
    • 参数也没法自动带过去。
  • 所以要用 fn.apply(context, args):
    • 保证 this 正确 → 就是调用 debounce 包裹函数时的 this。
    • 保证参数不丢失 → args 是数组,apply 会把它展开传给 fn。
  1. 手撕new函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    function myNew(Constructor, ...args) {
    // create null obj, let its __proto__ pointed to constructor's prototype
    const obj = Object.create(Constructor.prototype);

    // execute constructor, bind this to obj
    const result = Constructor.apply(obj, args);

    return (result !== null && (typeof result === 'object' || typeof result === 'function'))
    ? result
    : obj;
    }

    function Person(name, age) {
    this.name = name;
    this.age = age;
    }
    Person.prototype.sayHi() = function() {
    console.log("Hi, I'm " + this.name);
    };

    const p1 = myNew(Person, 'Alice', 30);
    p1.sayHi();

  2. 手撕LRU,时间复杂度O(1)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class LRUCache {
    constructor(capacity) {
    this.capacity = capacity;
    this.map = new Map(); //有序表
    }

    get(key) {
    if (!this.map.has(key)) return -1;
    const value = this.map.get(key);
    this.map.delete(key);
    this.map.set(key, value);//放到队尾
    return value;
    }

    put(key, value) {
    if (this.map.has(key)) {
    this.map.delete(key);
    } else if (this.map.size >= this.capacity) {
    const firstKey = this.map.keys().next().value;
    this.map.delete(firsetKey);//找到并删除队首
    }
    this.map.set(key, value);
    }
    }

HTML5-CSS3高频问题

  1. 语义化
    • 在HTML页面结构中所用的标签都有意义。
    • 头部用head,主体用body,底部用foot。
    • 如何判断是否语义化:去掉CSS内容,页面结构显示内容较为正常。
    • 为什么语义化:让HTML结构更加清晰明了,方便团队合作利于开发,可以让浏览器更好的去解析,优化用户体验。
  2. H5C3的新特性
    • HTML5的新特性:语义化标签;音频视频;画布canvas;数据存储localStorage,sessionStorage;表单控件email,url,search等;拖拽释放API等
    • CSS3新特性:选择器:属性选择器、伪类选择器、伪元素选择器;媒体查询;文字阴影;边框;盒子模型boxing-size;渐变;过度;自定义动画;背景属性;2D与3D等。
  3. rem如何适配
    • rem是相对根元素的font-size属性来计算大小,通常做移动端适配。
  4. 移动端兼容问题
    • 当样式设置overflow:scroll/auto时IOS上滑动会卡顿。-webkit-overflow-scrolling: touch
    • 安卓环境下placeholder文字设置行高时会偏上。input由placeholder时不要设置行高。
    • 移动端字体小于12px时显示异常。先整体放大一倍,再用transform缩小。

JavaScript高频问题

  1. JS的组成部分
    • ECMA Script:JS的核心内容,基础语法。如var, for, 数据类型等。
    • 文档对象模型(DOM):DOM将HTML页面规划为元素构成的文档。
    • 浏览器对象模型(BOM):对浏览器窗口进行访问和操作(如提供浏览器特性,获取浏览器API)。
  2. JS内置对象
    • String, Boolean, Number, Array, Object, Function, Math, Date, RegExp
    • 常用内置对象:
      • Math: abs(), sqrt(), max(), min(), ...
      • Date: new Date(), getYear(), getHour(), ...
      • String: concat(), length, slice(), split(), ...
  3. 操作数组的方法
    • push(), pop(), sort(), shift(), unshift(), reverse(), concat(), join(), map(), filter, every(), some(), reduce(), isArray(), findIndex(), splice()
    • 哪些方法会改变原数组:push(), pop(), shift(), unshift(), sort(), reverse(), splice()
  4. 检测数据类型
    • typeof:判断基础数据类型,无法判断引用数据类型(class)。typeof 12345
    • instanceof():只能判断引用数据类型,无法判断基本数据类型。[] instanceof Array
    • constructor:几乎可以判断基本数据类型和引用数据类型。('abc').constructor === String
    • Object.prototype.toString.call():解决以上方式的问题。Object.prototype.toString.call(2/'abc'/true/[]/{})
  5. 闭包特性
    • 函数嵌套函数,内部函数被外部函数返回并保存下来时会产生闭包。
      1
      2
      3
      4
      5
      6
      7
      function fn(param) {
      return function() {
      console.log(param);
      }
      }
      var foo = fn('abcd');
      foo()
      输出abcd
    • 特性:
      • 可以复用变量且该变量不会污染全局(变量始终保存在内存中,不会被垃圾回收机制回收)。
      • 缺点:闭包较多时对内存占用较多,导致页面性能下降。只有在IE浏览器中会导致内存泄露。
    • 使用场景:防抖、节流、需避免全局污染时。
  6. 前端内存泄漏
    • JS中已分配内存空间的对象为能及时释放清除,会导致长期占用内存的现象,导致内存资源可用性变差,最终导致运行效率降低,甚至内存泄漏。
    • JS的垃圾回收机制:自动释放长时间不用的内存资源。
    • 导致内存泄漏的原因:为声明直接赋值的变量、未清空的定时器、过度闭包、引用元素未被清除等。
  7. 事件委托(事件代理)
    • 利用事件冒泡机制,将子元素事件(event)绑定到父元素上。
    • 若子元素阻止事件冒泡(event.stop()),则委托不成立。
    • addEventListener('click', func_name, false)默认false,false控制事件冒泡,true为事件捕获。
    • 好处:提高性能,减少事件绑定,减少内存占用。
  8. 基本数据类型与引用数据类型
    • 基本数据类型:String, Number, Boolean, undefined, null等保存在中,直接保存数据。
    • 引用数据类型(复杂数据类型):Object, Function, Array等保存在中,类似于C语言的指针类型(或C++引用),保存引用数据类型的地址。加入声明两个引用类型变量引用同一个地址时,改变其中一个另一个也改变。
  9. 原型链
    • 原型就是一个普通对象,用于构造函数的实例,共享属性和方法;所有实例中引用的原型都是同一个对象。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      function Person() {
      this.say = function() {
      console.log('Hello');
      }
      }
      var p1 = new Person();
      var p2 = new Person();
      p1.say(); //p1和p2的say方法相互独立,需要存两个实例。
      p2.say();
    • 使用prototype可以把方法挂在原型上,不同实例共享同一内存。
      1
      2
      3
      4
      5
      Person.prototype.look = function() {
      console.log('Look');
      }
      p1.look();//p1和p2的look方法指向同一内存。
      p2.look();
    • __proto__可以理解为指针,实例对象中的属性指向构造函数的原型(prototype)。
    • 参照C++虚函数表机制。
    • JS中若把属性定义在Prototype上,只读时内存共享,一旦需要写入则创建拷贝(遮蔽)。
    • 原型链:一个实例对象在调用属性、方法时一次按照实例本身(Person)、构造函数原型(Person.prototype)、原型的原型(Object.prototype)上去查找。
  10. new操作符
    1. 创建空对象。
    2. 把空对象和构造函数通过原型链连接。
    3. 把构造函数的this绑定到新的空对象。
    4. 根据构造函数返回的类型判断,若为值则返回对象值,若为引用则返回引用。
  11. JS的继承机制
    • 原型链继承:方便简洁,容易理解;对象实例继承所有属性和方法,无法像父类构造函数传参。Child.prototype = new Parent()
    • 借用构造函数继承:在子类构造函数内部调用父类构造函数;使用apply()call()方法将父对象构造函数绑定在子对象上。在子类中写Parent.call(this, param)。解决了原型链实现继承无法向父类传参的问题;方法都在构造函数中定义,无法实现函数复用,且父类原型中定义的方法对子类不可见,所有类型只能使用构造函数模式。
    • 组合式继承:解决了原型链继承和构造函数继承的缺点;然而无论什么情况下都会调用两次父类构造函数(一次是创建子类原型时,另一次在子类构造函数内部)。
    • ES6的class类继承:Class通过extends关键字实现继承,实质是先创造出父类this对象在调用子类构造函数修改this。子类构造方法中必须调用super方法且只有在调用了super后才能使用this。简单易懂;对于不支持ES6的浏览器无法适用。
  12. JS的设计原理
    • JS引擎:编译器。
    • 运行上下文:浏览器中可调用的API(外部接口)。
    • 调用栈:函数调用顺序的数据结构。用于同步执行、递归、错误堆栈等场景。(JS是单线程,只有一个主线程)
    • 事件循环:由于JS是单线程,为防止卡死引入了异步机制。事件循环为调用栈为空时,从任务队列里取出一个回调,压入调用栈执行,重复这个过程。把耗时任务交给“外部系统 (浏览器内核的 Web APIs 或 Node 的 libuv)”,等结果好了,再通过 事件循环 (Event Loop) 安排执行回调函数。
    • 回调:是一个被当作参数传递的函数,在合适的时候被调用。在异步编程里,回调通常是“异步任务完成后要执行的代码”。
  13. JS中this的指向
    • 全局对象中this的指向:指向window。
    • 全局作用域或普通函数中的this:指向window。
    • this永远指向最后调用它的对象。(非箭头函数)
    • new关键词会改变this的指向。
    • applycall以及bind都可以改变this的指向。(非箭头函数)
    • 箭头函数中的this在定义时已被确定,箭头函数无this,看外层是否有函数,有就是外层函数的this,没有就是window。
    • 匿名函数中this永远指向window。(匿名函数的执行环境具有全局性)。
  14. Script标签中asyncdefer
    • 没有async与defer时:浏览器会立刻加载并执行指定的脚本。
    • async:加载和渲染后面元素的过程将与Script的加载和执行并行执行(异步)。
    • defer:加载Script与加载渲染元素异步完层,执行则在所有元素解析完成之后。
  15. setTimeout的最小执行时间
    • setTimeout:4ms
    • setInterval: 10ms
    • 由HTML5规定(浏览器可能会影响)
  16. ES6和ES5的区别
    • ES5: ECMA Script 5(ECMAScript2009);
    • ES6: ECMA Script 6(ECMAScript2015);
  17. ES6的新特性
    • 新增块级作用域(let,const)
      • 不能在同一个作用域内重复声明。
      • 不存在变量提升。
      • 存在暂时性死区问题
    • 新增定义类(class)
    • 新增一种数据类型(symbol):代表独一无二的值,即使内容一致。
    • 新增结构赋值:从数据或者对象中取值赋给变量。
    • 新增函数参数默认值
    • 新增数组API
    • 新增对象和数组的扩展运算符
    • 新增Promise
      • 表示未来才会完成的值,用于解决回调地狱的问题。
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        const p = new Promise((resolve, reject) => {
        setTimeout(() => {
        resolve("任务完成"); // 或 reject("出错了")
        }, 1000);
        });

        p.then(result => {
        console.log(result);
        }).catch(error => {
        console.error(error);
        });
      • 自身有all,reject,resolve,rece这些方法。原型上有then,catch方法。
      • 把异步操作序列话,按预期返回结果。
      • 三种状态:pending(初始),fulfilled(操作成功),rejected(操作失败)。一旦状态转变就会凝固。
      • async与await:同步代码做异步操作,必须搭配使用。是Promise的语法糖。在函数面前添加async会自动返回一个Promise。遇到await暂停执行,等待Promise完成再继续。
    • 新增模块化(import,export)
    • 新增set和map数据结构
    • 新增generator
    • 新增箭头函数
      • 不能作为构造函数使用,不能用new。
      • 箭头函数没有arguments。
      • 不能使用call,apply,bind去改变this的执行
      • 无prototype。
  18. call, apply, bind的区别
    • 都是改变this指向和函数调用。
    • call与apply类似,只是传参方法不同。
    • call传参数列表。
    • apply传一个数组。
    • bind传参后不会立即执行,会返回一个改变了this指向的函数,这个函数可传参,通过bind()()来调用。
    • call方法性能比apply好一些,bind无法构造函数。
  19. 递归的问题
    • 递归:函数内部调用函数本身(递归函数必须有退出条件,否则会导致栈溢出)。
  20. 深拷贝的实现
    • 完全拷贝一个新的对象,在堆中重新开辟新的空间。拷贝的对象被修改后,原对象不受影响。
    • 主要针对引用数据类型。
    • 扩展运算符:只能针对第一层深拷贝,对于多层对象只是浅拷贝。
      1
      2
      3
      4
      5
      let obj1 = {
      name: "jack",
      age: 23
      };
      let obj2 = {...obj};
    • JSON.parse(JSON.stringify()):原对象中若有函数则不会被拷贝过来。
    • 利用递归函数:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      function copy(origin, isDeepCopy=true) {
      let result = {};
      if (origin instanceof Array) {
      result = [];
      }
      for (let key in origin) {
      let v = origin[key];
      result[key] = (!!isDeepCopy && typeof v === 'object' && v !== null) ? copy(v, isDeepCopy) : v;
      }
      return result;
      }
  21. 事件循环
    • JS是一个单线程脚本语言。
    • 主线程:唯一线程上任务。
    • 执行栈:任务栈,存储上下文与执行顺序。
    • 任务队列:任务调度。
    • 宏任务/微任务:异步任务,微任务优先级更高。
    • 主线程先执行同步任务,再执行任务队列里的微任务或宏任务。执行完再去查询任务队列,或者执行主任务。
  22. AJAX
    • 创建交互式网页应用的开发技术,再不重新加载整个页面的情况下与服务器交换数据并更新部分内容。
    • 通过XMLHttpRequest对象向服务器发送异步请求,返回数据后通过JS操作DOM的形式更新页面。
    • 过程:
      • 创建XMLHttpRequest对象。
      • 通过XMH对象里的open()方法与服务器建立连接。
      • 构建请求所需的数据,并通过XMH的send()方法发送至服务器。
      • 通过XMH对象的onReadyStateChange事件监听服务器与本地的通信状态。
      • 接受并处理服务器响应的结果。
      • 将处理结果更新到HTML页面中。
  23. GETPOST的区别
    • GET一般获取数据,POST一般提交数据。
    • GET参数在URL中,安全性较差。
    • POST参数在body中,数据长度无限制。
    • GET请求刷新服务器或退回无影响,POST请求退回时重新提交数据。
    • GET请求会被缓存,POST不会。
    • GET会被保存在浏览器的历史记录中,POST不会。
    • GET只能进行url编码,POST支持多种数据结构。
  24. Promise的内部原理与优缺点
    • Promise对象封装了一个异步操作且可以获取成功或失败的结果。
    • Promise主要解决回调地狱的问题,若之前异步任务较多且之间包含依赖关系就只能用回调函数解决,这样会导致代码可读性差、可维护性差形成了回调地狱。
    • Promise的三种状态:Pending,Fulfilled,Rejected。只能从Pending变为后者其中之一且不可逆。
    • Promise无法被取消,一旦创建立即执行,无法中断。
    • 如果不设置回调,Promise内部抛出的错误无法反馈到外面。
    • 原理:
      • 构造一个Promise实例需要传递一个函数作为参数,该函数有两个形参切都是函数类型,一个是resolve另一个是reject。
      • Promise上还有then方法,用来指定状态发生改变时的确定操作,resolve执行第一个函数,reject执行第二个函数。
  25. Promise与async、await的区别
    • 都是异步处理请求方式。
    • Promise是ES6,async和await是ES7.
    • async与await都是基于Promise实现的,都是非阻塞的。
    • 优缺点:
      • Promise是一个返回对象需要用then和catch来捕获,且书写方式是链式的容易造成代码重叠不好维护。而async和await通过try-catch来捕获异常。
      • async await最大的优点是让代码看起来像同步一样,只要遇到await就会立刻返回结果然后再执行后面的操作。而Promise.then()的方式会出现请求还没返回就执行了后面操作的情况。
  26. 浏览器的存储方式
    • cookies:H5标准前的本地存储方式;兼容性好,请求头自带cookie;存储量小容易造成资源浪费,使用麻烦(需要封装)。
    • localStorage:H5加入的标准方式,以key-value的形式存储。操作方便、永久存储、兼容性好;保存值的类型可能被限定,浏览器隐私模式下不可读取,不能被爬虫。
    • sessionStorage:类似于localStorage;当前页面关闭后会被立即清理,会话级别的存储方式。
    • indexedDB:H5标准存储方式,key-value存储,可以快速读取,适合web场景。
  27. token的存储位置
    • token:验证身份的令牌,一般是用户通过账号密码登录后,服务端把这些凭证通过加密等一系列操作后得到的字符串。
    • 若存在localStorage里,后期每次请求接口都需要把它当作一个字段传给后台,容易被XSS攻击。
    • 若存在cookie中会自动发送,不能跨域,会有CSRF攻击。
    • 一般存在localStorage/sessionStorage中,具体看需求。
  28. token的登录流程
    1. 客户端用账号密码请求登录。
    2. 服务端收到请求后验证账号密码。
    3. 验证成功后,服务端签发一个token发送给客户端。
    4. 客户端收到token保存后。
    5. 后续客户端每次向服务端发送资源请求时,都需要携带这个token。
    6. 服务端收到请求后验证token。成功则返回资源。
  29. 页面渲染的过程
    • DNS解析-建立TCP连接-发送HTTP请求-服务端处理请求-渲染页面-断开TCP
    • 渲染页面:
      • 获取HTML和CSS资源,把HTML解析成DOM树。
      • 解析CSS为CSSOM。
      • 把DOM和CSSOM合并为渲染树。
      • 把渲染树每个节点渲染到页面上(绘制)。
  30. DOM树与渲染树
    • DOM树是HTML标签的一一对应,包括head和隐藏元素。
    • 渲染树不包含head和隐藏元素。
  31. 精灵图与base64
    • 精灵图:多张图拼接后压缩,前端若要请求多张图片可以只请求一次。
    • base64:单张图片二进制信息转译为字符串(字符串大小可能比原图大)。
  32. svg格式
    • 基于XML语法格式的图像格式,可缩放矢量图。
    • svg可直接插入页面中,用JS或css对其进行操作。<svg></svg>
    • 也可以作为图像文件被引入。
    • 可以转为base64引入。
  33. JWT
    • JSON Web Token通过JSON形式在web应用中的令牌,可以在各方之间安全的把信息作为JSON对象传输。
    • 用作信息传输、授权。
    • 如果用session来验证会导致服务端负载过大,不利于负载均衡。
    • JWT认证流程:
      • 前端把账号密码发送给后端接口。
      • 后端核对信息,把用户id等信息作为JWT负载,把它和head分别进行base64编码后拼接的签名,形成一个JWT Token。
      • 前端每次请求时都会把JWT放在请求头的Authorization位置。
      • 后端检查是否存在,如果存在就验证JWT的有效性(签名是否正确,token是否过期等)。
      • 验证后后端使用JWT中包含的用户信息进行其他的操作,并返回对应结果。
    • JWT简洁、可跨语言使用。
  34. npm的底层环境
    • node package manager,node的包管理和分发工具,已经成为分发node的标准。是JS的运行环境。
    • 组成:网站、注册表(每一个包基本信息的数据库),命令行工具。
  35. HTTP协议规定包含的响应头和请求头
    • 请求头信息:
      • Accept:浏览器告诉服务器所支持的数据类型。
      • Host:浏览器告诉服务器像访问的主机。
      • Referer:浏览器告诉服务器我从哪里来(防盗链)。
      • User-Agent:浏览器类型、版本。
      • Date:浏览器告诉服务器我是什么时候访问的。
      • Connection:连接方式。
      • Cookie
      • X-Request-With:请求方式。
    • 响应头信息:
      • Location:告诉浏览器你要去找谁。
      • Server:告诉浏览器服务器的类型。
      • Content-Type:告诉浏览器返回的数据类型。
      • Refresh:控制定时刷新。
  36. 浏览器的缓存策略
    • 强缓存(本地缓存):不发起请求,直接使用缓存中的内容,浏览器把JS,CSS,image等内容存到内存中,下次访问时直接从内存中取。
    • 弱缓存(协商缓存):需要向后台发请求,通过判断来决定是否使用协商缓存,如果请求内容没有变化,则返回304,浏览器使用缓存里的内容。
    • 强缓存的触发:HTTP1.0用时间戳响应标头;HTTP1.1用Cache-Control响应标头。
    • 弱缓存的触发:HTTP1.0用if-modified-since响应头last-modified;HTTP1.1用if-none-match响应头Etag。
  37. 同源策略
    • 浏览器的基本(核心)安全策略,URL中协议、域名以及端口号完全相同即为同源。不一样则产生跨域。
    • 三个允许跨域加载资源的标签:img,link,script。
    • 跨域是可以正常发送请求的,后端也会返回结果,只不过该结果被浏览器拦截。
    • 解决跨域的方式:JSONP(服务端允许),CORS(服务端和客户端同时配置),websocket,反向代理(中转站)。
  38. 防抖和节流
    • 都是应对页面中频繁触发事件的优化方案。
    • 防抖:触发事件后,在一段时间内只执行最后一次。如果在这段时间内事件又被触发,就重新计时。
      • 频繁和服务端交互
      • 输入框自动保存时间
    • 节流:触发事件后,在固定时间间隔内只执行一次。不管事件触发多少次,都会按照时间间隔来执行。
      • 页面滚动监听 → 每 200ms 计算一次位置。
      • 鼠标拖拽 → 每 100ms 更新一次位置。
  39. JSON
    • JSON是纯字符串形式数据,适合在网络中传输,不提供任何方法。
    • JSON数据存储在.json文件中,或者以字符串形式在数据库、cookie中。
    • JS提供了JSON.parse(), JSON.stringify()方法。
    • 使用场景:定义接口、序列化、生成token、配置文件。
  40. 数据请求失败的做法
    • 在渲染数据的地方给默认值。
    • if判断,没有数据可以隐藏。
  41. 无感登录
    • 无感刷新token,token失效时自动更新。
    • 在响应拦截器中拦截,token过期后调用刷新token的接口。(常用)
    • 后端返回过期的时间,前端判断token的过期时间,主动调用刷新token的接口。
    • 写定时器,定时刷新token。
    • 流程:
      • 登录成功后保存token和refresh_token。
      • 响应拦截器中对401状态码引入刷新token的api方法调用。
      • 替换保存本地新的token。
      • 把错误对象里的token替换。
      • 再次发送未完成请求。
      • 如果refresh_token也过期,清除所有token返回登录页面。
  42. 大文件上传
    • 分片上传:把需要上传的文件按一定规则分割成大小相同的数据块。
      • 初始化分片上传任务,返回本次上传的唯一标识。
      • 按照一定规则把各个数据块上传。
      • 发送完成后服务端判断数据完整性,若完整则合并。
    • 断点续传:
      • 服务端返回从哪里开始/浏览器自己处理。
  43. varletconst的区别
    • 作用域:
      • var在函数内声明则只作用于函数内部,其他情况都是全局作用域。
      • let/const是在花括号内有效。
    • 变量提升:
      • var声明会被提升(hoist),初始化为undefined。声明之前访问为undefined。
      • let/const也会被提升,但是会有TDZ(Temporary Dead Zone),在声明之前访问会报错。
    • 重复声明:
      • var可以重复声明同名变量。
      • let/const在同一作用域内不允许重复声明。
    • 是否可以重新赋值:
      • var/let:可以重新赋值。
      • const:声明后必须立刻赋初值,且不能重复赋值。
    • 对象/数据的const特殊性:const只是保证变量绑定(引用)不可辨,但对象/数组的内容可以被改变。

CSS高频问题

  1. CSS盒模型
    • 在HTML页面中的所有元素都可以看作一个盒子。
    • 盒子的组成:内容content,内边距padding,边框border,外边距margin。
    • 盒模型的类型:
      • 标准盒模型:margin + border + padding + content。
      • IE盒模型:margin + content(border + padding)。
    • 控制盒模型的模式:box-sizing : content-box (default,标准盒模型), border-box(IE盒模型)。
  2. CSS选择器优先级
  • CSS的特性:继承性、层叠性、优先级。
  • 优先级:写CSS样式时给同一个元素添加多个样式,此时样式权重高的则优先显示。
  • 选择器:!important > 行内样式 > id > 类/伪类/属性 > 标签 > 全局选择器。
  1. 如何隐藏元素
    • display: none; (元素直接消失,不占据空间)
    • opacity: 0; (透明度为0,占据空间)
    • visibility: hidden; (元素消失,占据空间)
    • position: absolute;(移除页面)
    • clip-path (剪切元素)
  2. pxrem的区别
    • px是像素,显示器上呈现画面的像素,大小统一的绝对单位。
    • rem是相对单位,相对于HTML根节点的font-size的值。
      • 若设定HTML根结点font-size为62.5%, 则1rem = 10px
      • 16px * 62.5% = 10px。(默认状态下1rem = 16px
  3. 重绘与重排的区别
    • 重排(回流):布局引擎根据所有样式计算盒模型在页面中的位置和大小;对DOM的大小、位置等属性进行修改后需要重新计算几何属性,就叫重排。
    • 重绘:计算完成盒模型的位置、大小等属性之后,浏览器会根据每个盒模型的特性在页面上绘制;对DOM的样式进行修改后,浏览器不需要重新计算几何属性直接绘制该元素新样式,就叫重绘。
    • 浏览器的渲染机制浏览器渲染机制
  4. 让元素水平垂直的方式
    • 定位+margin:子元素设置top: 0; bottom: 0; left: 0; right: 0; margin: auto;
    • 定位+transform:子元素设置top: 50%; left: 50%; transform: translate(-50%, -50%);
    • flex布局:父元素设置display: flex; justify-content: center; align-items: center;
    • table布局:父元素设置display: table-cell; vertical-align: middle;,子元素设置margin: 0 auto;
    • grid布局:父元素设置display: grid; justify-items: center;
  5. 属性继承
    • 子元素可以继承父元素的样式:
      • 字体类属性:font…
      • 文本类属性:text-align, line-height…
      • 元素可见性:visibility: hidden…
      • 表格布局:border-spacing…
      • 列表属性:list-style…
      • 页面样式:page…
      • 声音样式
  6. 预处理器
    • CSS弊端:样式重复使用,不利于扩展维护。
    • 预处理:增加变量、函数、混入等强大功能。类似于宏定义,通过编译器替换变量、函数等。
      • SASS与LESS
      • @global-color: #EEE; box { color: @global-color; }

燈塔只是信標, 帶不走過客的錨。 歲月不再豐饒, 只有海水無情, 看著新大陸的孤島。

寒刀劈水掣天洪,殘花依舊綉春風。 乖看河東新鞍馬,幾時颯沓長安宮。

附黃巢《不第后賦菊》 待到秋來八九月,我花開后百花殺。 冲天香陣透長安,滿城盡帶黃金甲。