关于前端

1. 框架类:

1.1 vue

  • 原理;
  • v-key的作用(diff 算法):"就地复用"策略,高效的更新虚拟DOM;
  • 组件传参;
  • 组件按需加载:
// vue异步组件
component: require('@/pages/login')
// webpack 可结合 webpack 做一些加工处理
component: r => require.ensure([], () =>; r(require('@/components/home')), 'chunk')
// es6
component: () => import('@/pageslogin')
  • 动态渲染图片;
  • 数组数据响应方法;
  • Methods、computed、watch 区别:methods 在调用时才会计算。computed 当依赖的数据变化时才会计算, 当数据没有变化时, 它会读取缓存数据。watch 会在属性变化后重新计算。
  • data为什么是函数:为了达到数据隔离,由于组件可以复用,当组件被实例化后,属性也会被创建在原型链上,因此需要用data 返回一个可独立维护的数据拷贝;
  • nextTick 实现方式:Promise.resolve(),渐弱:setTimeout();
  • axios 原理:axios可用于浏览器和 node.js 中,它会根据当前环境选择实现方式。如果是浏览器环境中,会基于XMLHttpRequests实现axios。如果是node.js环境,就会基于node内置 http模块 实现axios;
  • 路由实现方式及原理:hash模式,根据 window.location.hash 读取地址变化,监听 hashchange 事件来响应;history模式,通过H5新增的两个api window.history.pushStatewindow.history.replaceState 来实现路由切换,监听 popstate 来响应。参考:vue-router 原理

1.2 react

  • 事件绑定 this 丢失:绑定事件时,传递的不是字符串,而是一个方法,onClick 即为中间变量,render 方法执行过程会丢失原来的 this 引用;
  • hook

1.3 小程序

  • 压缩、组件传参(设计模式)、胶囊按钮的位置
  • 双线程模型:
  • 外部样式引用:externalClasses
  • behavior:
  • wxs 文件的功能
  • 与vue双向邦定的区别

1.4 Webpack

  • Plugin

    • webpack整体是一个插件架构,所有的功能都以插件的方式集成在构建流程中,通过发布订阅事件来触发各个插件执行。webpack核心使用Tapable来实现插件(plugins)的binding(绑定)和applying(应用)。
    • Compiler 模块是 webpack 的支柱引擎,它通过 CLI 或 Node API 传递的所有选项,创建出一个 compilation 实例。它扩展(extend)自 Tapable 类,以便注册和调用插件。大多数面向用户的插件首先会在 Compiler 上注册。
  • 配置项: entry、output、module( loader )、plugins、devServer、resolve、devtool、optimization。

  • 多入口配置

    • entry 选项配置多入口的目录,同时配置 HtmlWebpackPlugin 生成对应 html 模板。chunks 表示 html 文件的入口chunks;
    • vendor 是指提取涉及 node_modules 中的公共模块,manifest 是对 vendor 模块做的缓存

2. CSS:

2.1 布局

  • 左侧固定,右侧自适应宽度;
  • 垂直水平居中;

2.2 样式实现

  • 三角形、正方形;

2.3 异常的处理

  • 移动端兼容行高 line-height (Android、IOS)
  • margin 溢出

2.4 移动端布局兼容

  • rem

2.5 盒模型、包裹性、BFC

3. JavaScript:

3.1 原始类型 => 装箱拆箱 => 对象构造 => new 操作符 => 箭头函数、普通函数区别 => 闭包 =>; 垃圾回收(标记清除)

3.2 数据类型的判断(typeof,constructor,instance of,Object.prototype.toString.call())

3.3 js线程 => 事件循环 => 异步执行顺序

3.4 浏览器绘制页面 => 重绘重排

3.5 面向对象 继承(原型继承、构造继承、组合继承等)

3.6 深拷贝(Date、reg类型)

const isObject = (target) => (typeof target === "object" || typeof target === "function") && target !== null;
function deepClone(target, map = new WeakMap()) {
    if (map.get(target)) {
        return target;
    }
    // 获取当前值的构造函数:获取它的类型
    let constructor = target.constructor;
    // 检测当前对象target是否与正则、日期格式对象匹配
    if (/^(RegExp|Date)$/i.test(constructor.name)) {
        // 创建一个新的特殊对象(正则类/日期类)的实例
        return new constructor(target);  
    }
    if (isObject(target)) {
        map.set(target, true);  // 为循环引用的对象做标记
        const cloneTarget = Array.isArray(target) ? [] : {};
        for (let prop in target) {
            if (target.hasOwnProperty(prop)) {
                cloneTarget[prop] = deepClone(target[prop], map);
            }
        }
        return cloneTarget;
    } else {
        return target;
    }
}

3.7 URL 参数提取

function parseParam(url) {
    const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将 ? 后面的字符串取出来
    const paramsArr = paramsStr.split('&'); // 将字符串以 & 分割后存到数组中
    let paramsObj = {};
    // 将 params 存到对象中
    paramsArr.forEach(param => {
        if (/=/.test(param)) { // 处理有 value 的参数
            let [key, val] = param.split('='); // 分割 key 和 value
            val = decodeURIComponent(val); // 解码
            val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字
    
            if (paramsObj.hasOwnProperty(key)) { // 如果对象有 key,则添加一个值
                paramsObj[key] = [].concat(paramsObj[key], val);
            } else { // 如果对象没有这个 key,创建 key 并设置值
                paramsObj[key] = val;
            }
        } else { // 处理没有 value 的参数
            paramsObj[param] = true;
        }
    })
    
    return paramsObj;
}

3.8 this 绑定(new操作符、bind等、上下文调用绑定、默认绑定window)

3.9 new 关键字实现

// new 会产生一个新对象
// 新对象需要能够访问到构造函数的属性,所以需要重新指定它的原型
// 构造函数可返回
function objectFactory() {
    var obj = new Object()
    Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    var ret = Constructor.apply(obj, arguments);
    
    // ret || obj 这里这么写考虑了构造函数显示返回 null 的情况
    return typeof ret === 'object' ? ret || obj : obj;
};

3.10 call、apply、bind 模拟实现

Function.prototype.call = function (context) {
    var context = context || window;
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }

    var result = eval('context.fn(' + args +')');

    delete context.fn
    return result;
}

3.11 防抖节流原理

3.12 跨域的处理方式: CORS、代理

3.13 require 、import 区别

  • require是“运行时加载”,只有在代码真正运行的时候才会去加载对应需要的东西,所以不能做到编译时就把想加载的模块加载进来,即不能做到编译时静态化
  • import是编译时调用,所以必须放在文件开头

3.14 JS编译解析的流程

  • 语法分析,生成抽象语法树(AST)和执行上下文:
    • 生成 AST 需要经过两个阶段:
      • 第一阶段是分词(tokenize),又称为词法分析
      • 第二阶段是解析(parse),又称为语法分析
  • 预编译,解释器 lgnition 生成字节码
  • 解释执行,第一次执行,解释器 lgnition 通常会一行行执行代码,解释过程中,若发现一段代码被重复执行多次,即为热点代码,则 编译器 TurboFan 会把该段热点的字节码编译为机器码,再次执行这段被优化的代码时,只需要执行编译后的机器码就可以了,这样就大大提升了代码的执行效率。这就是 即时编译(JIT)

3.15 设计模式:

  • 发布订阅 (Publish Subscribe Pattern) -- 多个订阅者对象同时监听某一个主题对象,这个主题对象状态变化时,会通知所有订阅者对象,使它们能够自动更新自己的状态
  • 代理模式 (Proxy Pattern) -- 当对一个对象的访问不能直接引用时,可通过一个称之为 “代理” 的中间层来实现间接引用。通过引入代理对象来间接访问一个对象

3.16 面向对象的基本特征: 封装、继承、多态 => Class =>; prototype;

3.17 promise、promise.all、promise.finally 模拟实现、async/await

3.18 ES6 +

  • 箭头函数与普通函数的区别

    • 没有this,会捕获其所在的上下文的this值
    • 不能作为构造函数,不能使用 new
    • 不绑定arguments,用rest参数...解决
    • 没有原型属性
    • 不能当做Generator函数,不能使用yield关键字
  • 解构

  • 运算符(扩展运算符... 可选链?. 空值合并?? )

参考
死磕 36 个 JS 手写题

4. TypeScript:

5. Node.js:

  • handleCount
  • koa、中间件

6. HTTP:

  • 超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求 - 响应协议,归属于应用层协议,主要解决如何包装数据。
  • 三次握手、四次挥手
  • TCP、UDP
  • 安全:xss、csrf
  • 跨域:cors(预检请求)

7. 浏览器:

7.1 浏览器的渲染原理

  • 根据 html 文档,构建一棵 DOM 树,由元素及其附加属性组成。
  • 对 CSS 解析,生成 CSSOM 规则树,样式规则。
  • 根据 DOM 树和 CSSOM 规则树构建渲染树 Render Tree。由一些包含颜色和大小等属性的矩形组成。
  • 根据 Render Tree 来布局,计算各节点的位置、大小,此过程也就是“重排”。
  • 绘制。遍历render树,调用 Paint 方法使用 UI 基础组件绘制出来。这个过程并非是等 html 完全解析完再执行,而是解析完一部分就执行显示一部分。如下图,

JavaScript 的加载,解析,执行 都会阻塞文档的解析;

CSS 是并行下载,不会阻塞后面 JS 的下载,但会阻塞后面 JS 的执行;

CSS 不会阻塞 DOM 的解析,但会阻塞 DOM 渲染。

因此,script 标签被建议放在body 标签底部,CSS 被建议放在头部。

7.2 缓存机制

  • 7.2.1 浏览器的缓存过程:
    1. 域名解析,DNS缓存:域名查找IP地址的过程就是dns解析,这个过程会对网络请求带来一定的损耗,浏览器第一次解析后会将其缓存起来,即 DNS缓存。

      • 下次识别到相同地址时,会先查找本地缓存,优先使用本地缓存;
      • DNS缓存不存在,读取系统的hosts文件查找对应映射关系,若存在,则域名解析到此完成;
      • 本地hosts文件不存在映射关系,查找本地DNS服务器,若存在,域名到此解析完成;
      • 本地DNS服务器未找到,向服务器发送请求解析IP。
    2. 内存缓存(memory缓存):缓存于本地内存中,页面关闭,内存释放;

      • HTTP缓存(强缓存和协商缓存):硬盘缓存,最主要的缓存方式,可控且优化空间大的一个缓存部分,也是面试中常问的一个缓存环节;
      • 服务端缓存(CDN缓存):CDN节点解决了跨运营商和跨地域访问的问题,访问延时大大降低。浏览器本地缓存的资源过期之后,会向服务器发起资源申请,优先转向 CDN 边缘节点请求资源,CDN 中的缓存可用,直接返回,不可用或者过期,CDN 边缘节点会向源服务器发出回源请求,从而来获取最新资源,并做缓存。
  • 7.2.2 HTTP缓存的命中方式:
    1. 根据 http 中的 header 判断是否命中强缓存,若命中,则直接从本地缓存中获取资源,不发送服务器请求;
    2. 强缓存未命中时,浏览器发送服务端请求,通过请求头验证是否命中协商缓存,若命中,则返回请求,但不返回资源,而是通知浏览器从本地加载资源;
    3. 都未命中,直接从服务器加载资源。
  • 7.2.3 强缓存:
    1. 利用 Expires(HTTP/1.0)、Cache-Control(HTTP/1.1)这些请求头参数,控制资源过期时间。到了HTTP/1.1,Expires已经被Cache-Control替代,所以,这两个字段同时存在时,Cache-Control优先级高于Expires。
      • Cache-Control 主要取值:
        1. max-age:指定一个时间长度,在这个时间段内缓存是有效的,单位是s。
        2. s-maxage:同 max-age,覆盖 max-age、Expires,但仅适用于共享缓存,在私有缓存中被忽略。
        3. public:所有内容都将被缓存(客户端和代理服务器都可缓存)
        4. private:所有内容只有客户端可以缓存,Cache-Control的默认取值
        5. no-cache:在使用已缓存的数据前,发送带验证器的请求到服务器,不是字面意思上的不缓存。
        6. no-store:禁止缓存,所有内容都不会被缓存,既不使用强制缓存,也不使用协商缓存,每次请求都要向服务器重新获取数据。

    参考 浏览器缓存命中策略

    1. 使用时,在Web服务器返回的响应中添加 ExpiresCache-Control Header。
    2. 控制台显示为,状态码 Status: 200, size: (from cache)。
  • 7.2.4 协商缓存:
    1. 某个资源的请求没有命中强缓存,会向服务器发送请求验证协商缓存是否命中,若命中,浏览器会收到304的响应,就会从缓存中加载资源。
    2. 大部分web服务器都默认开启协商缓存,同时启用 Last-Modified,If-Modified-Since (资源在服务器上最后修改时间)和 ETag、If-None-Match (资源的唯一标识)控制。
    3. 控制台显示为,状态码 Status: 304 Not Modified 。
/**
*
*    ┏┓     ┏┓
*   ┏┛┻━━━━━┛┻┓
*   ┃      ┃
*   ┃  ━   ┃
*   ┃ ┳┛ ┗┳  ┃
*   ┃      ┃
*   ┃  ┻   ┃
*   ┃      ┃
*   ┗━┓   ┏━┛ Code is far away from bug with the animal protecting
*     ┃   ┃    神兽保佑,代码无bug
*     ┃   ┃
*     ┃   ┗━━━┓
*     ┃      ┣┓
*     ┃      ┏┛
*     ┗┓┓┏━┳┓┏┛
*      ┃┫┫ ┃┫┫
*      ┗┻┛ ┗┻┛
*
*/
posted @ 2020-04-14 11:34  晨の风  阅读(144)  评论(0编辑  收藏  举报