跳至主要內容

yyshino大约 47 分钟FrontEnd面经

CSS

BFC

【定义】

块级格式上下文,web独立的渲染区域,不会影响边界外的元素

【形成条件】

1、浮动float 2、非静态定位position为absolute或fixed 3、display为inline-block、table-cell、table-caption、flow-root、flex 或 inline-flex 元素的直接子元素、grid 或 inline-grid 元素的直接子元素 4、overflow不为visible 5、contain 值为 layout、content 或 paint 的元素

【BFC特性】

1、内部box会在垂直方向,一个接一个地放置。 2、Box垂直方向的距离由margin决定,在一个BFC中,两个相邻的块级盒子的垂直外边距会产生折叠。 3、在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘) 4、形成了BFC的区域不会与float box重叠 5、计算BFC高度时,浮动元素也参与计算

【主要应用】

1、利用特性4可实现左图右文之类的效果; 2、利用特性5可以解决浮动元素造成的父元素高度塌陷问题; 3、解决外边距合并问题; 4、右侧盒子自适应:BFC区域不会与浮动盒子产生交集,而是紧贴浮动边缘。

定位Position

  • static:正常定位,正常的布局行为(此时 top, right, bottom, leftz-index 属性无效。)
  • relative:相对定位,在不改变页面布局的前提下调整元素位置
  • absolute:绝对定位,元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于<html>,绝对定位完全脱离文档流与文本流,不占据文档空间
  • fixed:固定定位,相对于窗口进行偏移定位,
  • sticky:粘性定位,
    • 如果top、right、bottom、left四个属性都不设置具体值,sticky(粘性定位)不会生效,其表现效果与static一致
    • 当在top、right、bottom、left四个属性中至少设置一个具体值时,元素具备两种状态 — 类似relative(相对定位状态)和类似fixed(固定定位状态)

布局Flex Grid

Flex

  • Flex布局也称弹性布局,可以为盒状模型提供最大的灵活性,是布局的首选方案,现已得到所有现代浏览器的支持。(设为 Flex 布局以后,子元素的floatclearvertical-align属性将失效。)

  • 容器属性

    • flex-direction:决定主轴方向 (row column

    • flex-wrap:当轴线放不下成员时,是否换行 (wrap nowrap)

    • flex-flow:前两个属性(flex-direction flex-wrap)的缩写

    • justify-content:成员在主轴上的对齐方式 (flex-start flex-end center space-between space-around

    • align-items:成员在交叉轴上如何对齐 (flex-start flex-end center stretch baseline

      • stretch默认值:如果成员未设置高度或设为auto,将占满整个容器的高度。
      • baseline: 成员的第一行文字的基线对齐。
    • align-content:属性定义了多根轴线的对齐方式。如果成员只有一根轴线,该属性不起作用,取值为flex-start | flex-end | center | space-between | space-around | stretch

  • 成员属性

    • order:定义成员的排列顺序,数值越小,排列越靠前,默认为0
    • flex-grow:属性定义成员的放大比例,默认为0
    • flex-shrink:属性定义了成员的缩小比例,默认为1,即如果空间不足,该成员将缩小
    • flex-basis:属性定义了在分配多余空间之前,成员占据的主轴空间main size,浏览器根据这个属性,计算主轴是否有多余空间,它的默认值为auto,即成员的本来大小。
    • flex:属性是flex-grow, flex-shrinkflex-basis的简写,默认值0 1 auto。后两个属性可选。
    • align-self:**属性允许单个成员有与其他成员不一样的对齐方式,可覆盖align-items属性。**默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch

盒子模型

content-box:默认值,widthheight属性分别应用到元素的内容框。在宽度和高度之外绘制元素的marginborderpadding,称为标准盒子模型

border-box:为元素设定的widthheight属性决定了元素的边框盒,就是说,为元素指定的任何内边距和边框都将在已设定的宽度和高度内进行绘制。通过从已设定的宽度和高度分别减去borderpadding才能得到内容的宽度和高度,称为IE盒子模型

inherit:规定应从父元素继承box-sizing属性的值。

------------------------------------------
|                 margin                 |  
| -------------------------------------- |
| |               border               | |
| | ---------------------------------- | |
| | |             padding            | | |
| | | ------------------------------ | | |
| | | |           content          | | | |
| | | |                            | | | |
| | | |                            | | | |
| | | ------------------------------ | | |
| | ---------------------------------- | |
|  ------------------------------------- |
------------------------------------------

行内元素与块元素

行内元素(Inline Elements)和块级元素(Block-level Elements)是 HTML 中两种常见的元素类型,它们在布局和显示上有一些区别。

  1. 行内元素(Inline Elements):
    • 默认情况下,行内元素不会独占一行,它们会在同一行上水平排列。
    • 行内元素的宽度和高度由内容决定,无法设置固定的宽度和高度。
    • 行内元素不会自动换行,超出父容器宽度时会被截断或溢出。
    • 行内元素可以设置水平方向的边距(margin-left、margin-right)、内边距(padding-left、padding-right)和边框(border)。
    • 常见的行内元素有 <span>、<a>、<em>、<strong>、<img>、<input> 等。
  2. 块级元素(Block-level Elements):
    • 块级元素独占一行,默认情况下会从新行开始,并在上下方留有空白间距。
    • 块级元素的宽度默认为父容器的100%,可以通过设置宽度和高度属性来改变其尺寸。
    • 块级元素会自动换行,即使内容没有占满一行,也会强制换到下一行。
    • 块级元素可以设置垂直方向的边距(margin-top、margin-bottom)、内边距(padding-top、padding-bottom)和边框(border)。
    • 块级元素可以容纳其他元素作为其子元素。
    • 常见的块级元素有 <div>、<p>、<h1>~<h6>、<ul>、<li>、<section>、<article> 等。

CSS Modules

它是CSS 命名冲突和全局污染的一种解决方案,在构建过程中,CSS Modules 将样式文件中的类名进行哈希处理,生成唯一的类名

  1. 在构建过程中,CSS Modules 将样式文件中的类名进行哈希处理,生成唯一的类名,例如 .container 可以变为 .container_1a2b3c
  2. 在组件中,通过导入样式文件,可以在 JavaScript 代码中引用样式对象。例如,import styles from './styles.module.css';
  3. 在组件的 HTML 结构中,可以使用样式对象中定义的类名,例如 <div class={styles.container}>...</div>
  4. 运行时,样式对象中的类名会被替换为实际的唯一类名,确保样式仅在当前组件内生效。

CSS的引入当时有哪些

  • 外部样式表(External Stylesheet):使用<link>标签将外部CSS文件引入到HTML文档中。这是最常用的方式,可以在多个页面之间共享样式,使得样式的维护和管理更加方便。
  • 内联样式(Inline Styles):使用style属性直接将样式规则嵌入到HTML元素中。这种方式适用于只在特定元素上应用特定样式的情况,但不方便复用和统一管理。
  • 嵌入样式(Embedded Styles):使用<style>标签将样式规则直接嵌入到HTML文档的<head>标签中。这种方式适用于只在当前页面使用的样式,但对于样式的复用和管理不够方便。
  • @import规则:使用CSS的@import规则在样式表中引入其他CSS文件。这种方式可以在一个样式表中引入多个外部CSS文件,但由于它是同步加载的,会导致阻塞页面渲染,不推荐使用。

@import与link引入有什么区别

加载方式:

  • @import@import是CSS的一种规则,可以在CSS文件中使用,用于引入其他CSS文件。它是在CSS解析过程中执行的,会阻塞页面的渲染,直到所有的样式文件都加载完成。
  • <link>:使用<link>标签可以在HTML文档的<head>部分中引入外部CSS文件。它是在HTML解析过程中进行加载的,并行下载,不会阻塞页面的渲染。

兼容性:

  • @import:@import规则在早期的浏览器版本中可能存在一些兼容性问题。例如,一些较旧的IE浏览器不支持在@media规则中使用@import。
  • <link>:使用<link>标签引入外部CSS文件是标准的HTML方式,具有良好的兼容性,适用于所有主流浏览器。

功能扩展:

  • @import:由于@import是CSS规则,可以在CSS文件中使用,因此可以在媒体查询(@media)内使用@import来根据设备或浏览器的特定条件加载不同的样式文件。
  • <link>:使用<link>标签还可以通过rel属性指定不同的关联类型,如icon、preconnect等,用于引入其他资源和建立预连接等功能。

JavaScript

JS数据类型

js的基础数据类型和复杂数据类型

  1. 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型 string ,number,boolean,undefined,null、BigInt、Symbols
  2. 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型 通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等

深浅拷贝

  • 常用深拷贝方式

    1. Object.assign:默认是对对象进行深拷贝的,但是我们需要注意的是,它只对最外层的进行深拷贝,也就是当对象内嵌套有对象的时候,被嵌套的对象进行的还是浅拷贝;

    2. JSONJSON.parse(JSON.stringify(obj))JSON会自己去构建新的内存来存放新对象。)

      1. JSON.parse(JSON.stringify(obj))的缺点
        1. 忽略 undefinedsymbol
        2. 不可以对Function进行拷贝,因为JSON格式字符串不支持Function,在序列化的时候会自动删除;
        3. 诸如 Map, Set, RegExp, Date, ArrayBuffer 其他内置类型在进行序列化时会丢失
        4. 不支持循环引用对象的拷贝;(循环引用的可以大概地理解为一个对象里面的某一个属性的值是它自己)
    3. MessageChannel(会忽略 undefined;不能序列化函数;不能解决循环引用的对象)

    4. 递归 (不能解决循环引用的问题)

      function cloneDeepDi(obj){
        const newObj = {};
        let keys = Object.keys(obj);
        let key = null;
        let data = null;
        for(let i = 0; i<keys.length;i++){
          key = keys[i];
          data = obj[key];
          if(data && typeof data === 'object'){
            newObj[key] = cloneDeepDi(data)
          }else{
            newObj[key] = data;
          }
        }
        return newObj
      }
      

作用域

  1. 全局作用域(Global Scope):
    • 全局作用域是在代码中任何位置都可以访问的最外层作用域。
    • 在全局作用域中声明的变量和函数可以被所有其他作用域访问。
  2. 函数作用域(Function Scope):
    • 函数作用域是在函数内部声明的变量和函数可被函数内部访问的作用域。
    • 函数作用域遵循「函数级作用域」的原则,函数内部可以访问外部作用域中的变量和函数,但外部作用域无法访问函数内部的变量和函数。
  3. 块级作用域(Block Scope):
    • 块级作用域是在代码块(例如 if 语句、for 循环、函数内部)中声明的变量和函数的作用域。
    • 在 ES6(ECMAScript 2015)之前,JavaScript 只有全局作用域和函数作用域,没有块级作用域。
    • 在 ES6 中引入了 letconst 关键字,可以用于在块级作用域中声明变量,限制变量的作用范围在当前块内部。

作用域链(Scope Chain)是用于查找变量的机制。当代码中访问一个变量时,JavaScript 引擎会沿着作用域链向上查找,直到找到第一个匹配的变量或达到全局作用域。

闭包

JavaScript 闭包(Closure)是指函数可以访问并操作其词法作用域外的变量的能力。简单来说,闭包是由函数以及函数内部能访问的变量组成的组合体。

闭包的特点包括:

  1. 函数嵌套:闭包通常是由函数嵌套创建的,内部函数可以访问外部函数中的变量。
  2. 变量访问:内部函数可以访问外部函数中声明的变量,即使外部函数执行完毕,这些变量依然可被内部函数访问。
  3. 保留状态:闭包使得函数可以记住并保留对其词法作用域的引用,即使在函数外部被调用。

原型链

对象对象的构造函数原型对象

JavaScript 原型链(Prototype Chain)是一种对象之间继承关系的机制。它用于在对象之间共享属性和方法,并实现对象的属性查找和继承。

在 JavaScript 中,每个对象都有一个内部属性 [[Prototype]]__proto__),它指向另一个对象,这个对象被称为原型(Prototype)。如果在当前对象上找不到某个属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的顶端。

__proto__prototype

  • __proto__ 是对象的属性,用于指向该对象的原型。
  • prototype 是构造函数的属性,用于指向构造函数创建的对象的原型。

事件循环

事件循环的执行过程

  • 同步代码,调用栈执行后直接出栈
  • 异步代码,放到Web API中,等待时机,等合适的时候放入回调队列(callbackQueue),等到调用栈空时eventLoop开始工作,轮询
  • 微任务执行时机比宏任务要早

宏任务和微任务有哪些

在 JavaScript 中,宏任务(Macro Task)和微任务(Micro Task)是用于管理和调度异步操作的机制。它们有以下几个常见的来源:

宏任务(Macro Task):

  • setTimeout 和 setInterval 定时器回调函数
  • DOM 事件监听器回调函数
  • 用户交互事件的回调函数(如点击事件、输入事件)
  • XMLHttpRequest 和 fetch 的回调函数
  • Node.js 中的 I/O 操作回调函数

微任务(Micro Task):

  • Promise 的回调函数(resolve 和 reject)
  • MutationObserver 的回调函数
  • process.nextTick(Node.js 环境)

执行顺序和优先级:

  • 在 JavaScript 中,宏任务会先于微任务执行。
  • 当执行栈为空时,会首先执行所有微任务队列中的任务,直到微任务队列为空。
  • 接下来,会从宏任务队列中选择一个任务执行。
  • 这个过程会循环进行,直到所有的任务都执行完成。

垃圾回收机制

标记清除、

weakmap

Promise

  • 三个状态:

    • 初始态pending:创建Promise对象时的初始状态,这个初始状态会随着你调用resolve,或者是reject函数而切换到另一种状态。
    • 成功态resolved:调用resolve()方法
    • 失败态rejected:调用reject()方法
  • resolve的返回值

    • Promise.resolve(value) 方法返回一个以给定值解析后的 Promise 对象。
      • 如果这个值是一个 promise,那么将返回这个 promise;
      • 如果这个值是 thenable(即带有 then 方法),返回的 promise 会“跟随”这个 thenable 的对象,采用它的最终状态;
      • 否则返回的 promise 将以此值完成。此函数将类 promise 对象的多层嵌套展平。

Async/Await

Async/Await 是 JavaScript 中处理异步操作的一种语法糖,它建立在 Promise 的基础上,提供了一种更简洁、更易于理解和编写的方式来处理异步代码。

使用 Async/Await 可以将异步代码以同步的方式编写,避免了回调地狱(Callback Hell)和嵌套过深的问题。它的核心是通过 async 函数和 await 关键字来实现。

下面是 Async/Await 的基本用法:

  1. async 函数:
    • async 函数是一个返回 Promise 对象的函数。
    • 在函数体内,可以使用 await 关键字暂停执行并等待一个 Promise 对象的解决(或拒绝)。
    • async 函数内部可以包含多个 await 表达式,按照顺序依次执行。
  2. await 关键字:
    • await 关键字只能在 async 函数内部使用。
    • 在遇到 await 表达式时,会暂停 async 函数的执行,直到等到 Promise 对象的状态变为 resolved(解决)并返回结果,或者变为 rejected(拒绝)并抛出错误。
    • await 表达式后面可以是一个 Promise 对象,或者任何返回 Promise 对象的表达式(例如异步函数调用、fetch 请求等)。

js怎么将多维数组转换成一维数组

  1. 转换成字符串
  2. 递归

ES6新特性

块级作用域和常量、箭头函数、类和模块化、解构赋值、Promise、模板字符串、默认参数值、扩展运算符、迭代器和生成器、模块化导入和导出、简化对象属性和方法的定义

ES6(ECMAScript 2015)是 JavaScript 的一个重要版本,引入了许多新的语言特性和改进。以下是 ES6 中一些主要的新特性:

  1. 块级作用域和常量:引入了 letconst 关键字,可以在块级作用域内声明变量和常量,取代了原来的 var 关键字。
  2. 箭头函数:使用箭头函数语法 () => {} 可以更简洁地声明函数,并且自动绑定了函数体内的 this 值。
  3. 类和模块化:引入了 class 关键字,可以使用面向对象的方式定义和继承类。此外,还支持模块化的语法,通过 importexport 关键字实现模块的导入和导出。
  4. 解构赋值:可以从数组或对象中快速提取值并赋给变量,简化了变量的声明和赋值操作。
  5. Promise:引入了 Promise 对象,用于更好地处理异步操作,避免了回调地狱,提供了更优雅和可读性更高的代码结构。
  6. 模板字符串:使用反引号(``)包裹字符串,可以在字符串中插入变量和表达式,更方便地拼接字符串。
  7. 默认参数值:在函数声明时可以为参数设置默认值,简化了函数调用时的参数传递。
  8. 扩展运算符和剩余参数:使用 ... 运算符可以将数组或对象展开,以及收集函数参数中的剩余参数。
  9. 迭代器和生成器:引入了迭代器和生成器的概念,使得数据的遍历和操作更加灵活和简便。
  10. 模块化导入和导出:使用 importexport 关键字可以实现模块化的导入和导出,更好地组织和管理代码。
  11. 简化对象属性和方法的定义:可以使用简洁的语法定义对象属性和方法,不再需要重复书写键和值。

箭头函数和普通函数的区别

  1. 语法简洁性:箭头函数的语法更加简洁,可以通过去除function关键字和使用箭头符号来定义函数。这使得箭头函数更易读、更紧凑。
  2. this 的绑定:箭头函数没有自己的 this 值,它会继承外层函数的 this 值。而普通函数的 this 值根据函数的调用方式和上下文发生变化。
  3. arguments 对象:箭头函数没有 arguments 对象,无法直接访问函数的参数列表。而普通函数可以通过 arguments 对象获取传入的参数。
  4. 构造函数:箭头函数不能用作构造函数,无法使用 new 关键字来实例化对象。而普通函数可以通过 new 关键字来创建实例。
  5. 作为方法:由于箭头函数没有自己的 this 值,因此不适合作为对象的方法。普通函数则可以通过对象的方法调用方式来绑定合适的 this 值。
  6. 嵌套函数:在箭头函数中,this 值继承自外层函数,而不是指向函数本身。这使得箭头函数在嵌套函数中的行为更直观,不会因为函数嵌套而改变 this 的指向。

es6基础题目,对象能解构赋值吗?如果你要实现该怎么加上一个迭代器

对象能解构赋值

ES6 中的对象是可以进行解构赋值的。

对象解构赋值是一种从对象中提取值并赋值给变量的语法。它允许你通过对象的属性名称来匹配和提取对象中的值,并将其赋值给变量。

怎么加上迭代器

我们通过给对象 person 添加一个具有 Symbol.iterator 键的属性,并将其值设置为一个生成器函数(function*)来创建迭代器。生成器函数使用 yield 关键字返回每个属性的键值对。然后,我们可以使用 for...of 循环来迭代对象,并以 [key, value] 的形式访问每个属性的键和值。

Reflect

Reflect 是 ES6 中引入的一个内置对象,它提供了一组用于操作对象的方法。

script标签的属性

src:指定要引入的外部JavaScript文件的URL。使用该属性可以将外部的JavaScript文件加载到HTML文档中。

async:指示浏览器异步加载脚本,不阻塞 HTML 文档的解析。当脚本文件可独立执行且无需依赖其他脚本时,可以使用 async 属性以提高性能。

defer:指示浏览器延迟脚本的执行,直到 HTML 文档解析完成。与 async 不同的是,defer 保证脚本的执行顺序与它们在 HTML 中的顺序一致。

integrity:用于提供脚本的完整性校验,可以确保脚本在引入过程中没有被篡改。需要配合使用 Subresource Integrity (SRI) 来计算并提供 hash 值。

module:用于指定脚本以模块方式加载,这允许使用 ES6 模块化语法进行脚本编写。需要注意的是,当使用 module 属性时,脚本文件必须位于同源策略下。

NodeJS

NodeJS有什么特点

Node.js 具有异步非阻塞、单线程、轻量高效和跨平台等特点,适用于构建高性能、可扩展的网络应用和服务器端应用。它的出现极大地推动了 JavaScript 在服务器端的发展,为开发者提供了更多的选择和灵活性。

  • 异步非阻塞:Node.js 采用了事件驱动和非阻塞 I/O 的模型,使得它能够处理大量并发连接而不会阻塞线程。这种特性使得 Node.js 非常适合处理高并发的网络应用,如实时聊天、实时通信和实时数据传输等。
  • 单线程:Node.js 是单线程的,但是通过事件循环(event loop)和异步 I/O 操作,它可以实现高效的并发处理。相比于传统的多线程模型,Node.js 可以在单个线程上处理更多的请求,减少了线程切换的开销,提高了性能和资源利用率。
  • 轻量高效:Node.js 采用了轻量级的设计,它的核心部分非常小巧,具有高效的内存管理。它的模块化系统和包管理工具(npm)使得开发者可以方便地复用和共享代码,提高开发效率。
  • 跨平台:Node.js 可以运行在多个操作系统平台上,包括 Windows、macOS 和 Linux 等。这使得开发者可以使用相同的代码和工具在不同的平台上开发和部署应用程序。
  • 生态系统丰富:Node.js 拥有庞大而活跃的社区,有大量的开源模块和工具可供选择。通过 npm,开发者可以轻松地安装、管理和分享代码,快速构建复杂的应用程序。

Koa了解什么

Koa 是一个基于 Node.js 的轻量级 Web 应用框架,它旨在提供一种简洁、灵活和可扩展的开发方式。Koa 借鉴了 Express 的设计思想,但在语法和功能上进行了一些改进和优化。

Koa的一些特点和特性:

  1. 异步流程控制:Koa 使用基于 Promise 的异步流程控制,可以通过 async/await 语法编写更清晰、简洁的异步代码,避免了回调地狱。
  2. 中间件机制:Koa 的核心思想是中间件(Middleware),每个中间件可以处理请求和响应,并将控制权传递给下一个中间件。这种机制使得编写和组合中间件变得非常灵活,可以按需加载所需的功能。
  3. 上下文对象:Koa 将每个请求封装在一个上下文对象(Context)中,开发者可以通过上下文对象访问请求和响应的相关信息,如请求头、请求体、响应头等,方便进行操作和处理。

Vue2

请你说说Vue中v-model语法糖的实现

在 Vue.js 中,v-model 指令提供了一种简洁的语法糖,用于实现表单元素的双向绑定。它实际上是基于属性绑定(v-bind)和事件监听(v-on)的组合使用。

当我们在组件中使用 v-model 时,Vue 实际上会根据表单元素的类型和特定的属性,自动生成一个名为 value 的属性和一个名为 input 的事件监听器。这样就实现了将组件的属性和事件与表单元素的值和输入事件进行双向绑定。

源码双向绑定

Vue 2.x 的双向数据绑定是通过其响应式系统实现的,其中核心原理是使用了 Object.defineProperty 方法来劫持对象的属性访问,实现对数据的监控和响应。

具体实现步骤如下:

  1. 数据劫持(Data Observation):
    • 在 Vue 中,通过使用 Observer 对象对数据进行劫持。
    • 在劫持过程中,会遍历对象的所有属性,并使用 Object.defineProperty 方法将每个属性转换为 getter 和 setter。
    • 在 getter 中收集依赖,即建立属性和 Watcher 之间的联系。
    • 在 setter 中触发依赖,即当属性的值发生变化时,通知相关的 Watcher 进行更新。
  2. 依赖收集(Dependency Collection):
    • 在 Vue 的模板编译过程中,会解析模板中的指令和表达式,并创建对应的 Watcher 对象。
    • 在解析过程中,如果遇到数据绑定的表达式,会将该表达式与当前的 Watcher 建立联系。
    • 在数据劫持过程中的 getter 函数中,会收集当前 Watcher 对象作为依赖,将其添加到依赖列表中。
  3. Watcher 更新(Watcher Update):
    • 当数据发生变化时,会触发属性的 setter 函数。
    • 在 setter 函数中,会通知与该属性相关联的 Watcher 对象进行更新。
    • Watcher 对象接收到更新通知后,会执行相应的回调函数,进而更新视图。

通过以上步骤,Vue 2.x 实现了双向数据绑定的效果。当数据发生变化时,会自动更新相关的视图,同时,当视图发生变化时,也可以更新绑定的数据。

Vue3双向数据绑定

Diff算法

Vue 和 React 是两个流行的前端框架,它们在 Diff 算法的实现上有所不同。

  1. Vue 的 Diff 算法:
    • Vue 使用了一种基于双端队列的算法,称为"Virtual DOM with Keyed Diff"。
    • Vue 在更新过程中,通过对比新旧虚拟 DOM 树的节点,使用节点的 key 值进行匹配和定位。
    • Diff 算法的过程如下:
      1. 对比根节点:首先对比新旧虚拟 DOM 树的根节点,判断它们是否相同。
      2. 对比子节点:如果根节点相同,则对比它们的子节点。
        • Vue 使用双端队列,从新旧虚拟 DOM 树的两端开始对比,减少移动节点的操作。
        • Diff 算法会根据节点的 key 值进行匹配,找出相同节点的位置。
        • 如果节点相同,则进行递归对比它们的子节点。
        • 如果节点不同,则删除旧节点并插入新节点。
      3. 完成对比:当遍历完新旧虚拟 DOM 树的所有节点后,Diff 算法完成了对比过程。
  2. React 的 Diff 算法:
    • React 使用了一种称为"Reconciliation"的算法,基于 Fiber 架构实现。
    • React 的 Diff 算法是一种渐进式的增量更新算法,能够将更新操作分解成多个小任务,以提高性能和用户体验。
    • Diff 算法的过程如下:
      1. 对比根节点:首先对比新旧虚拟 DOM 树的根节点,判断它们是否相同。
      2. 构建 Fiber 树:如果根节点相同,则构建 Fiber 树,表示整个组件树的结构。
      3. Diff 阶段:在 Diff 阶段,React 通过 Fiber 树的遍历,对比新旧节点,并标记需要进行的操作。
        • React 使用多种启发式算法,如同级比较、key 值比较等,来快速确定需要更新的节点。
        • Diff 算法会尽量复用已存在的 DOM 节点,减少创建和销毁节点的开销。
      4. 提交阶段:在提交阶段,React 执行实际的 DOM 更新操作,将变更应用到真实的 DOM 树上。

$NextTick作用与原理

在 Vue 2 中,$nextTick 是一个实例方法,用于在 DOM 更新之后执行回调函数。它的作用是确保在下次 DOM 更新循环结束后执行回调,以获取更新后的 DOM 结构。

原理:

  1. 当调用 $nextTick 方法时,Vue 会将传入的回调函数存储到一个队列中,即异步回调队列。
  2. 在 Vue 的更新循环中,当所有同步任务执行完毕后,Vue 会开始执行异步回调队列中的回调函数。
  3. Vue 利用浏览器的宏任务(setTimeoutsetImmediate)或微任务(PromiseMutationObserver)机制,在下一个事件循环中执行异步回调队列的回调函数。
  4. 在执行回调函数时,Vue 会确保当前 DOM 更新已经完成,以便回调函数能够获取到最新的 DOM 结构。

适用场景

  • 在修改数据后,需要等待 Vue 更新 DOM 结构后再进行操作,如获取更新后的元素大小、滚动位置等。
  • 在组件生命周期钩子函数 mountedupdated 中,操作 DOM 元素,以确保操作在 DOM 更新后执行。

Vue父子组件生命周期

需要注意的是,父组件和子组件的生命周期钩子函数的执行顺序如下:

  • 父组件的 beforeCreate
  • 父组件的 created
  • 父组件的 beforeMount
  • 子组件的 beforeCreate
  • 子组件的 created
  • 子组件的 beforeMount
  • 子组件的 mounted
  • 父组件的 mounted
  • 父组件的 beforeUpdate
  • 子组件的 beforeUpdate
  • 子组件的 updated
  • 父组件的 updated
  • 父组件的 beforeDestroy
  • 子组件的 beforeDestroy
  • 子组件的 destroyed
  • 父组件的 destroyed

这些生命周期钩子函数允许开发者在组件的不同生命周期阶段执行相关的逻辑,例如在 created 钩子函数中进行数据初始化,在 mounted 钩子函数中进行 DOM 操作,在 beforeDestroy 钩子函数中进行资源清理等。

Vuex

当 Vuex 数据丢失时,可能是由于以下几个常见原因导致的:

  • 页面刷新
  • 浏览器关闭或标签页关闭

解决

  • 持久化存储:将 Vuex 的数据持久化存储到本地存储(如 localStorage 或 sessionStorage)
  • 使用插件:可以使用 Vuex 插件来处理数据的持久化存储
  • 后端存储:如果需要长期保存数据,并且多个用户之间需要共享数据,可以将数据存储到后端数据库中,通过接口进行数据的读取和更新。

Vue Router

  1. Hash 模式:
    • 在 hash 模式下,URL 中的路由会以 # 符号后面的部分表示,例如 http://example.com/#/home
    • hash 模式的优点是兼容性好,因为它不需要服务器配置特殊的规则。在不同的浏览器和服务器环境下,都可以正常工作。
    • hash 模式的缺点是 URL 中会出现 # 符号,有些人认为这样的 URL 不够美观。
  2. History 模式:
    • 在 history 模式下,URL 中的路由会直接使用正常的 URL 路径,例如 http://example.com/home
    • history 模式的优点是 URL 更加美观,没有 # 符号的干扰,更接近传统的 URL 格式。
    • history 模式的缺点是需要服务器的支持。为了确保在刷新页面或直接访问某个 URL 时能够正确加载对应的路由组件,需要配置服务器以返回同一个 HTML 页面,而不是 404 错误。

hash是如何实现的

在 hash 模式下,当用户访问一个带有路由信息的 URL 时,例如 http://example.com/#/home,浏览器会自动将 # 符号后面的部分识别为路由信息。Vue Router 利用这一特性,将应用的路由信息放在 URL 的哈希部分。

Vue Router 通过监听浏览器的 hashchange 事件来实现路由的切换。当 URL 的哈希部分发生变化时,Vue Router 就会根据新的哈希值来匹配对应的路由,并渲染相应的组件。

Vue Router 通过修改 location.hash 属性来改变 URL 的哈希部分,从而实现页面的路由切换。

Vue中的插槽Slot

Vue 中的插槽(Slot)是一种组件间通信的机制,用于在组件的模板中扩展和传递内容。它允许父组件向子组件传递内容,并在子组件中进行灵活的内容插入和分发。

插槽的作用类似于 HTML 中的占位符,允许开发者在父组件中定义模板结构,然后将内容插入到子组件的特定位置。

Vue中插槽的类型:默认插槽、具名插槽、作用域插槽

  • 默认插槽
    • 默认插槽是组件中的默认位置,用于插入父组件中没有放置在具名插槽中的内容。
    • 使用 <slot> 标签而不带任何属性即可定义默认插槽。
    • 在父组件中,将不带名称的内容放置在子组件的位置,即可被默认插槽接收并进行渲染。
  • 具名插槽
    • 具名插槽允许开发者在父组件中使用具有特定名称的插槽,并在子组件中根据名称进行插入。
    • 父组件中可以使用 <template> 标签来定义具名插槽,并在子组件中使用 <slot> 标签来表示插槽的位置。
    • 父组件可以在插槽位置插入任意内容,这些内容将被传递到子组件的对应插槽位置进行渲染。
    • 通过给 <slot> 标签添加 name 属性来定义具名插槽的名称,并在父组件中使用 <template v-slot:name> 或简写形式 #name 来插入内容到具名插槽中。
  • 作用域插槽
    • 解决父组件在使用插槽内容时需要访问子组件中的数据的需求。它通过在子组件中定义插槽,并将数据作为插槽的参数进行传递,使得父组件可以访问和使用这些数据。

Vue2和Vue3的主要区别

  • 响应式系统的变化:Object.defineProperty -> Proxy
  • 组合式API:新增选项式API
  • 性能优化
    • Vue 3在性能方面进行了一些优化,包括更高的渲染速度和更小的包体积。使用了更好的编译器优化和更精简的运行时代码。
    • Vue 3还引入了新的静态模板提升(Static Template Hoisting)技术,通过将静态节点提升为常量,减少了虚拟DOM的操作,提高了渲染性能。
  • TypeScript支持
    • Vue 3对TypeScript的支持更好,官方提供了完整的TypeScript声明文件,并在设计上考虑了TypeScript的类型推导。

Vue3

Proxy

Proxy和Object.defineProperty

Proxy 和 Object.defineProperty 都是 JavaScript 中用于对对象进行拦截和监听的机制,但在功能和使用方式上有一些区别。

  1. Object.defineProperty:
    • Object.defineProperty 是 JavaScript 中的一个原生方法,用于在一个对象上定义一个新的属性或修改现有属性的属性描述符。
    • 通过 Object.defineProperty,可以定义属性的特性,包括值(value)、可写性(writable)、可枚举性(enumerable)和可配置性(configurable)等。
    • Object.defineProperty 只能对单个属性进行操作,每次只能定义或修改一个属性。
    • Object.defineProperty 适用于对已存在的对象进行属性的控制和定义,常用于实现数据劫持和监听。
  2. Proxy:
    • Proxy 是 ES6 中新增的一个内置对象,用于创建一个代理对象,可以拦截并自定义对象的基本操作,如读取属性、写入属性、函数调用等。
    • 通过 Proxy,可以在对象上拦截多种操作,并在拦截器(handler)中定义自定义的行为。
    • Proxy 可以拦截更多的操作,而不仅限于单个属性的控制,包括属性的读取、写入、删除、函数调用、构造函数调用等。
    • Proxy 可以对整个对象进行代理,当对代理对象进行操作时,拦截器会捕捉到相应的操作并执行自定义的逻辑。
    • Proxy 提供了丰富的拦截方法,如 get、set、has、deleteProperty、apply 等,可以根据需要进行自定义拦截和处理。

在使用上,Object.defineProperty 是针对已有对象属性的定义和控制,需要逐个属性进行操作;而 Proxy 则是对整个对象进行代理,可以拦截并自定义多种操作,提供了更灵活和强大的功能。

需要注意的是,Proxy 是 ES6 中引入的新特性,对于一些老旧的浏览器可能不完全支持,而 Object.defineProperty 是较早的 JavaScript 特性,在大部分现代浏览器中得到支持。

React

打包和性能优化

webpack的基础配置是什么

  • 入口(entry)配置:指定应用程序的入口文件,Webpack从该文件开始解析和构建依赖关系图。
  • 输出(output)配置:指定打包后的文件输出目录和文件名。
  • 模式(mode)配置:指定构建模式,可选的值为developmentproductionnone
  • 模块(module)配置:用于定义如何处理项目中的不同类型的模块。
  • 插件(plugins)配置:用于执行一些额外的构建任务或优化资源。

webpack用过那些plugin,loader,他们的区别是什么

loader:

file-loader:把文件输出到一个文件夹中,在代码中通过相对URL引用输入的文件。 url-loader:和file类似,但能在文件很小的情况下以base64方式把文件内容注入到代码中。 image-loader:加载并压缩图片文件。 babel-loader:把ES6转换为ES5。 css-loader:加载CSS,支持模块化、压缩、文件导入等特性。 style-loader:把CSS代码注入到JavaScript中,通过DOM操作去加载CSS。 eslint-loader:通过ESlint检查JavaScript代码。

plugin:

define-plugin:定义环境变量。 commons-chunk-plugin:提取公共代码。 uglifyjs-webpack-plugin:缩小(压缩优化)js文件

区别

引用 webpack 官网 关于 loaderopen in new windowpluginopen in new window 的解释:

  • loader。webpack 自带的功能只能处理 javaScript 和 JSON 文件,loader 让 webpack 能够去处理其他类型的文件,并将它们转换成有效的模块,以及被添加到依赖图中。
  • plugin。插件可以执行范围更广的任务,包括打包优化,资源管理,注入环境变量

性能优化

高优先级:

  • 尽量减少帧数
  • CSS的数量-删除注释,空白空间等css文件是非阻塞的
  • 内联关键CSS(以上折叠CSS)
  • 避免嵌入/内联css
  • 分析样式表的复杂性
  • 压缩你的图像/保持图像数量低
  • 适当地选择你的图像格式
  • 缩小你的JavaScript不阻塞JavaScript:使用异步/延迟
  • 使用HTTPs在你的网站上
  • 保持你的页面重量<1500 KB(理想情况下<500kb
  • 保持你的页面加载时间<3秒
  • 保持时间到第一个字节<1.3秒
  • 尽量减少HTTP
  • 请求来自同一协议的文件
  • 避免请求不可达的文件(404)
  • 设置HTTP缓存头正确
  • gzip /Brotli压缩是启用的

中优先级:

  • 最小化的HTML -删除注释和空白空间
  • 使用内容交付网络
  • 更喜欢使用矢量图像而不是位图图像
  • 设置图像的宽度和高度属性(宽高比)
  • 避免使用Base64图像
  • 屏幕外的图像加载延迟(懒加载)
  • 确保提供接近你的显示尺寸的图像
  • 避免多个内嵌JavaScript片段<script>
  • 保持你的依赖最新
  • 检查你的JavaScript文件中的性能问题
  • Cookie大小应小于4096字节
  • 保持cookie计数小于20

低优先级:

  • 在可能的情况下预加载url
  • 将CSS连接到一个文件中
  • 删除未使用的CSS
  • Use WOFF2 font format
  • Use preconnect来加载你的字体
  • 更快保持网页字体大小在300kb以下
  • 防止Flash或不可见文本
  • 密切关注依赖项的大小

浏览器

跨域是什么?如何解决跨域?

1.什么是同源策略及其限制内容?

同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

同源策略限制内容有:

  • Cookie、LocalStorage、IndexedDB 等存储性内容
  • DOM 节点
  • AJAX 请求发送后,结果被浏览器拦截了

但是有三个标签是允许跨域加载资源:

  • <img src='xxx'>
  • <link href='xxx'>
  • <script src='xxx'>

跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。

  1. 跨域解决方案

    解决方案有jsonp、cors、postMessage、websocket、Node中间件代理(两次跨域)、nginx反向代理、window.name + iframe、location.hash + iframe、document.domain + iframe,CORS支持所有类型的HTTP请求,是跨域HTTP请求的根本解决方案,JSONP只支持GET请求,JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。不管是Node中间件代理还是nginx反向代理,主要是通过同源策略对服务器不加限制。日常工作中,用得比较多的跨域方案是cors和nginx反向代理

dom渲染在什么时候执行的

DOM 渲染是指将 HTML 文档解析成浏览器能够理解和显示的页面结构的过程。DOM 渲染的执行时机通常是在浏览器解析完 HTML 文档并构建出 DOM 树后进行的

DOM 渲染的执行过程如下:

  • 解析 HTML
  • 构建渲染树
  • 布局计算(重排)
  • 绘制(重绘)
  • 合成

浏览器渲染原理,重排重绘

浏览器的渲染原理涉及以下几个关键步骤:HTML 解析、CSS 解析、渲染树构建、布局计算、绘制和合成。

  1. HTML 解析:浏览器将接收到的 HTML 文档解析为 DOM 树(文档对象模型),表示了文档的结构和内容。
  2. CSS 解析:浏览器将解析 CSS 样式表,构建 CSSOM 树(CSS 对象模型),表示了文档的样式信息。
  3. 渲染树构建:浏览器根据 DOM 树和 CSSOM 树构建渲染树(Render Tree),渲染树只包含需要显示的节点,并且节点的样式信息已经与 DOM 树合并。
  4. 布局计算(重排):浏览器根据渲染树的信息,进行布局计算,确定每个节点在屏幕上的位置和大小。这个过程称为布局或重排,会触发对节点几何属性的计算和更新。
  5. 绘制(重绘):浏览器根据布局计算的结果,将渲染树的节点绘制到屏幕上,形成最终的可见图像。这个过程称为绘制或重绘,会触发对节点样式属性的绘制。
  6. 合成:浏览器将绘制好的图像进行合成,将不同图层的内容合成为最终的屏幕图像,以提高渲染性能。

重排(Reflow)和重绘(Repaint)是渲染过程中的两个重要概念:

  • 重排(Reflow):当 DOM 元素的几何属性发生改变,如尺寸、位置等,浏览器需要重新计算元素的几何属性,并重新进行布局计算和渲染,这个过程称为重排。重排会影响到整个渲染树,开销较大。
  • 重绘(Repaint):当 DOM 元素的样式属性发生改变,如颜色、背景等,浏览器会重新绘制元素的外观,而不影响布局,这个过程称为重绘。重绘的开销相对较小。

Cookie、LocalStorage 和 SessionStorage

是在 Web 开发中用于在浏览器端存储数据的三种机制。

  1. Cookie:
    • Cookie 是一小段文本信息,由服务器通过 HTTP 协议发送给浏览器,并存储在浏览器的本地文件中。
    • Cookie 主要用于跟踪用户会话、记录用户偏好设置等。它可以在浏览器和服务器之间进行数据传输。
    • Cookie 的特点包括:
      • 存储容量较小,一般为 4KB 左右。
      • 每次请求都会携带 Cookie 数据,增加网络流量。
      • 可设置过期时间,可以是会话级的(关闭浏览器即失效)或持久性的。
      • 可以设置域名和路径,控制 Cookie 的访问范围。
    • 通过 JavaScript 可以读取和修改 Cookie。
  2. LocalStorage:
    • LocalStorage 是 HTML5 提供的一种在浏览器端长期存储数据的机制。
    • LocalStorage 主要用于在用户浏览器中保存较大的数据,如用户配置、本地缓存等。
    • LocalStorage 的特点包括:
      • 存储容量较大,一般为 5MB 左右(不同浏览器可能有所差异)。
      • 数据在浏览器关闭后仍然存在。
      • 只能通过 JavaScript 进行读取和修改。
      • 数据以字符串形式存储,可以使用 JSON 进行序列化和反序列化。
      • 存储在同源的域名下,不同页面间可以共享数据。
  3. SessionStorage:
    • SessionStorage 也是 HTML5 提供的一种在浏览器端存储数据的机制,与 LocalStorage 类似。
    • SessionStorage 主要用于在用户浏览器中临时保存数据,与当前会话相关的数据。
    • SessionStorage 的特点包括:
      • 存储容量与 LocalStorage 相同,一般为 5MB 左右。
      • 数据在浏览器窗口关闭后会被清除。
      • 只能通过 JavaScript 进行读取和修改。
      • 数据以字符串形式存储,可以使用 JSON 进行序列化和反序列化。
      • 存储在同源的域名下,不同页面间可以共享数据。

Get和Post的区别

  1. 数据位置:
    • GET 方法将数据附加在请求的 URL 后面,以查询字符串(query string)的形式发送。
    • POST 方法将数据包含在请求的消息体(body)中发送。
  2. 数据长度限制:
    • GET 方法对发送的数据长度有限制,不同浏览器和服务器有不同的限制,通常在几千个字符左右。
    • POST 方法对发送的数据长度没有限制,但实际上服务器和网络设备也会有一定的限制。
  3. 数据安全性:
    • GET 方法将数据直接暴露在 URL 中,因此在网络请求、服务器日志、浏览器历史记录等地方都可以看到发送的数据。对于敏感数据(如密码),不宜使用 GET 方法。
    • POST 方法将数据包含在请求的消息体中,不会直接暴露在 URL 中,相对于 GET 方法更安全一些。但仍然需要注意使用加密协议(如 HTTPS)来保护数据的传输过程。
  4. 数据缓存:
    • GET 方法会被浏览器主动缓存,当再次请求相同 URL 时,浏览器可能直接使用缓存数据而不发送新的请求。
    • POST 方法不会被缓存,每次发送请求都会获取最新的响应。
  5. 幂等性:
    • GET 方法是幂等的,即多次相同的 GET 请求应该返回相同的结果,不会对服务器产生副作用(不会修改服务器状态)。
    • POST 方法不是幂等的,多次相同的 POST 请求可能会对服务器产生不同的结果或产生副作用(如创建资源)。

总结:

  • GET 方法适用于获取资源,请求参数通常以查询字符串形式附加在 URL 上。
  • POST 方法适用于提交数据,请求参数通常包含在请求的消息体中。
  • GET 方法数据暴露在 URL,长度有限,可能被缓存,幂等性;POST 方法数据不暴露在 URL,无长度限制,不被缓存,非幂等性。

提了一下缓存(协商缓存字段)

  • 强缓存是通过ExpiresCache-Control来控制缓存在本地的有效期。
  • 协商缓存是利用的是Last-Modified,If-Modified-SinceETag、If-None-Match这两对Header来管理的。(当浏览器对某个资源的请求没有命中强缓存,就会发一个请求到服务器,验证协商缓存是否命中,如果协商缓存命中,请求响应返回的HTTP状态为304 (Not Modified),该请求不携带实体数据,若未命中,则返回200并携带资源实体数据。协商缓存是利用的是Last-Modified,If-Modified-SinceETag、If-None-Match这两对Header来管理的。)

HTTP和HTTPS的区别

HTTP(超文本传输协议)和 HTTPS(HTTP 安全)是用于在客户端和服务器之间传输数据的协议,它们有以下区别:

  1. 安全性:
    • HTTP 是明文传输协议,数据在传输过程中不进行加密,容易被窃听和篡改。
    • HTTPS 使用 SSL/TLS 加密协议对数据进行加密,确保数据的机密性和完整性,更安全可靠。
  2. 默认端口:
    • HTTP 使用默认端口 80 进行通信。
    • HTTPS 使用默认端口 443 进行通信。
  3. 证书:
    • HTTPS 需要使用 SSL/TLS 证书来进行身份验证和加密通信。
    • HTTP 不需要证书,通信不被验证和加密。
  4. 连接建立过程:
    • HTTP 的连接建立过程较简单,是无状态的。每个请求和响应之间都是相互独立的。
    • HTTPS 的连接建立过程需要进行 SSL/TLS 握手,包括客户端和服务器之间的证书交换、密钥协商等,增加了连接的建立时间和计算开销。
  5. URL:
    • HTTP 的 URL 以 "http://" 开头。
    • HTTPS 的 URL 以 "https://" 开头。
  6. SEO 影响:
    • HTTPS 对搜索引擎优化(SEO)更加有利,搜索引擎更倾向于显示和排名使用 HTTPS 的网站。

总结:

  • HTTPS 是 HTTP 的安全版本,通过 SSL/TLS 加密协议保证数据的安全性和完整性。
  • HTTP 是明文传输协议,数据不进行加密,安全性较低。
  • HTTPS 需要证书验证和连接建立过程,而 HTTP 不需要。
  • HTTPS 使用默认端口 443,HTTP 使用默认端口 80。
  • HTTPS 对搜索引擎优化更有利。

websocke和http之间的不同

  • 连接方式:
    • HTTP:HTTP协议是一种无状态的请求-响应协议,客户端发送请求,服务器返回响应后即断开连接,每次请求需要建立新的连接。
    • WebSocket:WebSocket协议是一种全双工的、长连接的通信协议,它在客户端和服务器之间建立一条持久的连接,可以实现双向实时通信。
  • 数据传输:
    • HTTP:HTTP协议使用明文的、基于文本的数据传输,每次请求和响应都会携带HTTP头部和内容,通常使用JSON、XML等格式进行数据交换。
    • WebSocket:WebSocket协议使用二进制帧进行数据传输,可以直接发送和接收二进制数据,也支持文本数据。这使得WebSocket在传输效率上比HTTP更高。
  • 通信模式:
    • HTTP:HTTP协议采用的是客户端-服务器模式,客户端向服务器发起请求,服务器响应请求后返回结果,然后断开连接。
    • WebSocket:WebSocket协议支持客户端和服务器之间的双向通信,客户端和服务器可以随时互相发送数据。
  • 协议支持:
    • HTTP:HTTP协议被广泛支持,浏览器和服务器都内置了对HTTP的支持,可以通过URL进行请求和响应
    • WebSocket:WebSocket协议相对较新,需要服务器和客户端都支持WebSocket协议,而且需要通过特定的握手过程来建立连接
  • 应用场景:
    • HTTP:HTTP协议适用于客户端向服务器发起请求,获取资源的场景,如网页浏览、表单提交等。
    • WebSocket:WebSocket协议适用于需要实时双向通信的场景,如聊天应用、实时数据推送等。

职业规划

● 介绍一下前端的学习经历

● 为什么选择前端

● 作为一个专业的前端,你觉得应该掌握哪些知识

● 什么时候接触前端

● 大学学过哪些编程的课

● 选择前端的原因

● 对未来三年职业的规划

参考回答:

成为一个全栈工程师

● 你一般是通过什么方式学习前端的?

参考回答:

自学,W3school等网站,阮一峰、冴羽等大神的博客,GitHub,掘金,segmentfault等交流平台,

● 怎么学的前端?

● 看到你简历上有创客空间前端培训,是怎么样的形式?

● 你还有什么我没问到的优势吗

● 看过什么书

● 简单的介绍一下你自己,你知道哪些技术

● 为什么要选择web前端

● 比较厉害的技术

● 你为什么学前端,以及你学前端怎么坚持下来的

● 你认为一名前端工程师应该具备什么特点?一般是和产品,ui沟通做页面还是直接把图

● 如果直接按照图来做,有没有遇到过页面上实现不了的功能?遇到这样的问题怎么进行处理?

● 你一般是怎么学习前端的

● 看书的话,你是怎么判断书上的知识一定是对的?

● 也问了怎么学习前端的?看哪些书?

● 高程上面你觉得有什么地方是比较难理解的?

● 学过哪些框架?

● 我看见你写了一个js库,说一下有什么?

● 看过什么书?

● 有没有一页一页看?

● 你理解的框架

HR面

● 自我介绍

● 为什么要学习前端

● 一个前端工程师要做什么?

● 到现在为止接触过几个项目,有在哪里实习过?

● 让你收获最多的项目,你做了什么?

● 这个系统在代码方面有哪些不合理的地方?

● 个人的优缺点

● 读不读研

● 说说你最荣耀的事