Skip to content

面试题

TIP

说明:博客包括 HTML 面试题,CSS 面试题,JavaScript 基础面试题,ES6 面试题,webpack 面试题,Git 面试题,正则,Vue 面试题,微信小程序面试题等

第一章 面试题基础篇

1.1 HTML 面试题

面试题:Doctype 作用? 严格模式与混杂模式如何区分?它们有何意义?

INFO

  • <!DOCTYPE> 声明位于文档中的最前面,处于<html> 标签之前。告知浏览器以何种模式来渲染文档。

  • 严格模式的排版和 JS 运作模式是 以该浏览器支持的最高标准运行。

  • 在混杂模式中,页面以宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站点无法工作。

  • DOCTYPE不存在或格式不正确会导致文档以混杂模式呈现。

面试题:你知道多少种 Doctype 文档类型?

INFO

  • 该标签可声明三种 DTD 类型,分别表示严格版本、过渡版本以及基于框架的 HTML 文档。
  • HTML 4.01 规定了三种文档类型:Strict、Transitional 以及 Frameset。
  • XHTML 1.0 规定了三种 XML 文档类型:Strict、Transitional 以及 Frameset。
  • Standards (标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而 Quirks (包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页。

面试题:HTML 与 XHTML——二者有什么区别

INFO

区别:

  • 所有的标记都必须要有一个相应的结束标记
  • 所有标签的元素和属性的名字都必须使用小写
  • 所有的XML标记都必须合理嵌套
  • 所有的属性必须用引号""括起来
  • 把所有<和&特殊符号用编码表示
  • 给所有属性赋一个值
  • 不要在注释内容中使“--”
  • 图片必须有说明文字

面试题:行内元素有哪些?块级元素有哪些? 空(void)元素有哪些?

INFO

  • 行内元素:abstrongspanemimginputtextareaselectbutton ...

  • 块级元素:divfooterheadersectionpulollidldtddtableh1-h6...

  • 行内块元素:imginputtdaspanemstrongbiulabelbr

  • 空元素:brhrlinkmetacol...

  • 元素之间的转换问题:

    • display: inline 把某元素转换成了行内元素 ===>不独占一行的,并且不能设置宽高
    • display: inline-block 把某元素转换成了行内块元素 ===>不独占一行的,可以设置宽高
    • display: block 把某元素转换成了块元素 ===>独占一行,并且可以设置宽高

INFO

  • link 属于 html 标签,而@import 是 css 提供的
  • 页面被加载时,link 会同时被加载,而@import 引用的 css 会等到页面加载结束后加载。
  • link 是 html 标签,因此没有兼容性,而@import 只有 IE5 以上才能识别。
  • link 方式样式的权重高于@import 的。(@import 是将引⽤的样式导⼊到当前的⻚⾯中)

INFO

  • 区别一:link先有,后有@import(兼容性link比@import兼容);
  • 区别二:加载顺序差别,浏览器先加载的标签link,后加载@import

INFO

  • ① 从属关系
  • link:link是HTML提供的标签,不仅可以加载CSS,还可以定义rel等属性
  • @import:@import是css提供的语法,只有导入样式表的作用
  • ② 加载顺序
  • link:link在页面加载时CSS同时被加载
  • @import:引入的CSS要等页面加载完毕后再加载
  • ③ 兼容性问题
  • link是HTML提供的语法,不存在兼容性问题
  • @import是css2.1提供的语法,ie5以上才兼容
  • ④DOM 可控性
  • js控制DOM时,可以通过插入link标签来改变样式,不能通过@import改变
  • ⑤ 权重问题(有争议)
  • link标签引入的样式权重大于@import标签

面试题:title 与 h1 的区别、b 与 strong 的区别、i 与 em 的区别?

INFO

title与h1的区别:
  • 定义:
  • title:概括了网站信息,可以告诉搜索引擎或者用户关于这个网站的内容主题是什么
  • h1:文章主题内容,告诉蜘蛛我们的网站内容最主要是什么
  • 区别:
  • title他是显示在网页标题上、h1是显示在网页内容上
  • title比h1添加的重要 (title > h1 ) ==》对于seo的了解
  • 场景:
  • 网站的logo都是用h1标签包裹的

INFO

b与strong的区别:
  • 定义:
  • b:实体标签,用来给文字加粗的。
  • strong:逻辑标签,用来加强字符语气的。
  • 区别:
  • b标签只有加粗的样式,没有实际含义。
  • strong表示标签内字符比较重要,用以强调的。
  • 题外话:为了符合css3的规范,b尽量少用该用strong就行了。

INFO

i与em的区别:
  • 定义:
  • i:实体标签,用来做文字倾斜的。
  • em:是逻辑标签,用来强调文字内容的
  • 区别:
  • i只是一个倾斜标签,没有实际含义。
  • em表示标签内字符重要,用以强调的。
  • 场景:
  • i更多的用在字体图标,em术语上(医药,生物)

面试题:meta 干嘛用的

INFO

  • meta标签有下面的作用:
  • 1.搜索引擎优化(SEO)
  • 2.定义页面使用编码
  • 3.自动刷新并指向新的页面
  • 4.实现网页转换时的动态效果
  • 5.控制页面缓冲
  • 6.网页定级评价
  • 7.控制网页显示的窗口

INFO

  • name属性
  • name属性主要用于描述网页,与之对应的属性值为content,content中的内容主要是便于搜索引擎机器人查找信息和分类信息用的。

INFO

  • Keywords(关键字)

    • 说明:keywords用来告诉搜索引擎你网页的关键字是什么。
    • <meta name="keywords"content="meta总结,html meta,meta属性,meta跳转">
  • description(网站内容描述)

    • description用来告诉搜索引擎你的网站主要内容。
    • <meta name="description"content="haorooms博客,html的meta总结,meta是html语言head区的一个辅助性标签。">
  • author(作者)

    • 标注网页的作者
    • <meta name="author"content="root,root@xxxx.com">

面试题:img 标签的 title 和 alt 有什么区别?

  • 区别一

INFO

title : 鼠标移入到图片显示的值

alt : 图片无法加载时显示的值

  • 区别二:

INFO

在seo的层面上,蜘蛛抓取不到图片的内容,所以前端在写img标签的时候为了增加seo效果要加入alt属性来描述这张图是什么内容或者关键词。

面试题:png、jpg、gif 这些图片格式解释一下,分别什么时候用?

  • png:无损压缩,尺寸体积要比jpg/jpeg的大,适合做小图标。
  • jpg:采用压缩算法,有一点失真,比png体积要小,适合做中大图片。
  • gif:一般是做动图的。
  • webp:同时支持有损或者无损压缩,相同质量的图片,webp具有更小的体积。兼容性不是特别好。

面试题:什么是语义化标签

  • 易读性和维护性更好。
  • seo成分会好,蜘蛛抓取更好。
  • IE8不兼容HTML5标签的。解决:可以通过html5shiv.js去处理。

INFO

  • 好处
  • 语义类标签对开发者更为友好,使用语义类标签增强了可读性,即便是在没有 CSS 的时候,开发者也能够清晰地看出网页的结构,也更为便于团队的开发和维护。
  • 除了对人类友好之外,语义类标签也十分适宜机器阅读。它的文字表现力丰富,更适合搜索引擎检索(SEO),也可以让搜索引擎爬虫更好地获取到更多有效信息,有效提升网页的搜索量,并且语义类还可以支持读屏软件,根据文章可以自动生成目录等等。
  • 坏处
  • 不恰当地使用语义标签,反而会造成负面作用。这里我们举一个常见的误区作为例子。我们都知道 ul 是无序列表,ol 是有序列表,所以很多接触过语义这个概念,半懂不懂的前端工程师,特别喜欢给所有并列关系的元素都套上 ul

面试题:常见的浏览器内核有哪些?

  • Trident内核:IE,MaxThon,TT,The World,360,搜狗浏览器等。[又称MSHTML]
  • Gecko内核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey
  • Presto内核:Opera7及以上。 [Opera内核原为:Presto,现为:Blink;]
  • Webkit内核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]

1.2 CSS 面试题

面试题:介绍一下 CSS 的盒子模型

  • CSS的盒子模型有哪些:标准盒子模型IE盒子模型
  • CSS的盒子模型区别:
    • 标准盒子模型:marginborderpaddingcontent
    • IE盒子模型 :margincontentborder + padding + content
  • 通过CSS如何转换盒子模型:
    • box-sizing: content-box; /标准盒子模型/
    • box-sizing: border-box; /IE盒子模型/

面试题:line-heightheight 区别【大厂】

  • line-height是每一行文字的高,如果文字换行则整个盒子高度会增大(行数*行高)。
  • height是一个死值,就是这个盒子的高度。

面试题:CSS 选择符有哪些?哪些属性可以继承?

  • CSS选择符:

    • 通配(*)
    • id选择器(#)
    • 类选择器(.)
    • 标签选择器(div、p、h1...)
    • 相邻选择器(+)
    • 后代选择器(ul li)
    • 子元素选择器( > )
    • 属性选择器(a[href])
  • CSS属性哪些可以继承:

    • 文字系列:
    • font-size
    • color
    • line-height
    • text-align
    • word-break
    • letter-spacing
    • text-rendering
    • word-spacing
    • white-space
    • text-indent
    • text-transform
    • text-shadow
    • visibility
    • cursor
  • 不可继承属性:borderpaddingmargin...

面试题:CSS 优先级算法如何计算?

  • 优先级比较:!important > 内联样式 > id > class > 标签 > 通配

  • CSS权重计算:

  • 第一:内联样式(style) 权重值:1000
  • 第二:id选择器 权重值:100
  • 第三:类选择器 权重值:10
  • 第四:标签&伪元素选择器 权重值:1
  • 第五:通配、>、+ 权重值:0

面试题:CSS3 有哪些新特性?

  • 新增各种CSS选择器 (: not(.input):所有 class 不是“input”的节点
  • 圆角 (border-radius:8px
  • 多列布局 (multi-column layout
  • 阴影和反射 (Shadow\Reflect
  • 文字特效 (text-shadow
  • 文字渲染 (Text-decoration
  • 线性渐变 (gradient
  • 旋转 (transform
  • 缩放,定位,倾斜,动画,多背景
  • 例如:transform:\scale(0.85,0.90)\ translate(0px,-30px)\ skew(-9deg,0deg)\Animation

面试题:css 高度塌陷问题

  • 触发条件

    • 包含结构,所有的子元素浮动,且父元素没有设置高度,就会触发父元素高度塌陷。
  • 解决方法一

    • 给父元素添加固定高度。
    • 缺点:不适合高度自适应的布局。
  • 解决方法二

    • 给父元素添加overflow:hidden;
    • 缺点:不适合和定位定出去的页面布局使用
  • 解决方法三

    • 给所有的浮动盒子最后添加一个空的标签,例如 div,且添加声明 clear:both;
    • 缺点:多了很多空的标签,造成代码冗余。
  • 解决方法四

    • 万能清除浮动法。
    • 给塌陷的父元素:after{content:"";display:block;clear:both; visibility:hidden;}

面试题:css 让文字在一行内显示

  • 例如 p 元素,里面的文字不换行显示,超出部分不隐藏
css
p {
  width: 100px;
  word-break: keep-all;
  white-space: nowrap;
}
  • 例如 p 元素,里面的文字不换行,超出部分用省略号代替
css
p {
  width: 100px;
  word-break: keep-all;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

说明:

  • word-break:keep-all; /_ 不换行 / => 只能在半角空格或连字符处换行
  • white-space:nowrap; / 不换行 / => 规定段落中的文本不进行换行
  • overflow:hidden; / 内容超出宽度时隐藏超出部分的内容 /
  • text-overflow:ellipsis;
  • 当对象内文本溢出时显示省略标记(…) ; 需与 overflow:hidden; 一起使用
css
/* 单行文字省略号 */
.ellipsis {
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 多行文字省略号 */
.ellipsis {
  text-overflow: -o-ellipsis-lastline;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
}

面试题:弹性盒子布局 flex

  • 开启 flex 属性布局
css
display: flex;
  • 主轴排列方向:flex-direction(属性决定主轴的方向 即项目的排列方向)
  • flex-direction值:row 主轴为水平方向,起点在左端
  • row-reverse 主轴为水平方向,起点在右端
  • column 主轴为垂直方向,起点在上面
  • column-reverse 主轴为处置方向,起点在下沿
  • flex-flow 属性是 flex-direction 属性和 flex-wrap 属性的简写形式,默认值为 row nowrap
css
flex-flow: <flex-direction> <flex-wrap>;
  • 内容排列:justfy-content 属性定义了项目在主轴上的对齐方式

justify- content 定义了项目在主轴上的对齐

  • flex - start 左对齐
  • flex - end 右对齐
  • center 居中
  • space - around 盒子两侧间隔相等
  • space - between 两端对齐,中间间隔相等
  • align-item 属性定义项目在交叉轴上如何对齐
  • 它能取5个值。具体的对齐方式与交叉轴的方向有关
  • flex-start:交叉轴的起点对齐,垂直方向最上端。
  • flex-end: 交叉轴的终点对齐,垂直方向最下端。
  • center: 交叉轴的中点对齐,垂直方向中间。
  • baseline: 项目的第一行文字的基线对齐。
  • stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
  • align-self 属性
Internet Explorer 和 Safari 浏览器不支持 align-self 属性)
说明:
  • align-self 属性规定灵活容器内被选中项目的对齐方式。
  • 注意:align-self 属性可重写灵活容器的 align-items 属性。
  • 属性值
  • auto 默认值。元素继承了它的父容器的 align-items 属性。如果没有父容器则为 "stretch"。
  • Stretch 元素被拉伸以适应容器。
  • Center 元素位于容器的中心。
  • flex-start 元素位于容器的开头。
  • flex-end 元素位于容器的结尾。
  • align-content 属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用
  • align-content: flex-start | flex-end | center | space-between | space-around | stretch;
  • flex-wrap 属性
  • flex-wrap: nowrap(不换行) | wrap(换行) | wrap-reverse;(反向换行)
  • flex-basis 和 width 区别
  • basis英文意思是<主要成分>,所以他和width放在一起时,肯定把width干掉,basis遇到width时就会说我才是最主要的成分,你是次要成分,所以见到我的时候你要靠边站
flex-grow、flex-shrink、flex-basis三个属性的作用:
  • 在flex布局中,父元素在不同宽度下,子元素是如何分配父元素空间的。
  • (注意:这三个属性都是在子元素上设置的,下面小编要讲的是父元素,指以flex布局的元素(display:flex))
小编这里先教一下大家如何快速记住这三个属性:
  • 首先是 flex-basis ,basis英文意思是<主要成分>,所以他和width放在一起时,肯定把width干掉,basis遇到width时就会说我才是最主要的成分,你是次要成分,所以见到我的时候你要靠边站。
  • 其次是 flex-grow,grow英文意思是<扩大,扩展,增加>,这就代表当父元素的宽度大于子元素宽度之和时,并且父元素有剩余,这时,flex-grow就会说我要成长,我要长大,怎么样才能成长呢,当然是分享父元素的空间了。见下面第二个属性的内容
  • 最后是 flex-shrink, shrink英文意思是<收缩,>,这就代表当父元素的宽度小于子元素宽度之和时,并且超出了父元素的宽度,这时,flex-shrink就会说外面的世界太苦了,我还是回到父亲的怀抱中去吧!因此,flex-shrink就会按照一定的比例进行收缩

面试题:display 有哪些值?说明他们的作用。

INFO

  • none 隐藏元素
  • block 把某某元素转换成块元素
  • inline 把某某元素转换成内联元素
  • inline-block 把某某元素转换成行内块元素

INFO

  • block 块类型。默认宽度为父元素宽度,可设置宽高,换行显示。
  • none 元素不显示,并从文档流中移除。
  • inline 行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。
  • inline-block 默认宽度为内容宽度,可以设置宽高,同行显示。
  • list-item 象块类型元素一样显示,并添加样式列表标记。
  • table 此元素会作为块级表格来显示。
  • inherit 规定应该从父元素继承 display 属性的值。

面试题:对 BFC 规范(块级格式化上下文:block formatting context)的理解?

INFO

  • BFC就是页面上一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。
    1. 了解BFC : 块级格式化上下文。
    1. BFC的原则:如果一个元素具有BFC,那么内部元素再怎么弄,都不会影响到外面的元素。
    1. 如何触发BFC:

float的值非none

overflow的值非visible

display的值为:inline-blocktable-cell...

position的值为:absolutefixed

面试题:清除浮动有哪些方式?

    1. 触发BFC
    1. 多创建一个盒子,添加样式:clear: both;
    1. after方式
css
ul:after{
  content: '';
  display: block;
  clear: both
}

INFO

  • 使⽤空标签清除浮动 clear:both (缺点,增加⽆意义的标签)
  • 使⽤ overflow:auto (使⽤ zoom:1 ⽤于兼容 IE ,缺点:内部宽⾼超过⽗级 div 时,会出现滚动条)
  • after 伪元素清除浮动( IE8 以上和⾮ IE 浏览器才⽀持,⽬前:⼤型⽹站都有使⽤

面试题:在网页中的应该使用奇数还是偶数的字体?为什么呢?

INFO

  • 偶数 : 让文字在浏览器上表现更好看。偶数字号相对更容易和 web 设计的其他部分构成⽐例关系
  • 另外说明:ui给前端一般设计图都是偶数的,这样不管是布局也好,转换px也好,方便一点。

面试题:position 有哪些值?分别是根据什么定位的?

INFO

  • static [默认] 没有定位
  • fixed 固定定位,相对于浏览器窗口进行定位。
  • relative 相对于自身定位,不脱离文档流。
  • absolute 相对于第一个有relative的父元素,脱离文档流
  • sticky 粘性定位的元素是依赖于用户的滚动,在 position:relativeposition:fixed 定位之间切换
  • relativeabsolute区别

INFO

  • relative不脱离文档流 、absolute脱离文档流
  • relative相对于自身 、 absolute相对于第一个有relative的父元素
  • relative如果有leftrighttopbottom只有lefttop有效果
  • absolute如果有leftrighttopbottom 只有leftrighttopbottom有效果

面试题:为什么要初始化 CSS 样式

INFO

  • 因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。

  • 当然,初始化样式会对SEO有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化。

  • 最简单的初始化方法: * {padding: 0; margin: 0;} (强烈不建议)

面试题:什么是 CSS reset?

  • reset.css 是一个css文件,用来重置css样式的。
  • normalize.css 为了增强跨浏览器渲染的一致性,一个CSS 重置样式库。

面试题:css sprite 是什么,有什么优缺点

INFO

  • 是什么
  • 把多个小图标合并成一张大图片。
  • 优缺点
  • 优点:减少了http请求的次数,提升了性能。
  • 缺点:维护比较差(例如图片位置进行修改或者内容宽高修改)

面试题:display: none;与 visibility: hidden;的区别

INFO

  • 占用位置的区别
  • display: none; 是不占用位置的
  • visibility: hidden; 虽然隐藏了,但是占用位置
  • 重绘和回流的问题
  • visibility: hidden; 、 display: none; 产生重绘
  • display: none; 还会产生一次回流
  • 产生回流一定会造成重绘,但是重绘不一定会造成回流。
  • 产生回流的情况:改变元素的位置(left、top...)、显示隐藏元素....
  • 产生重绘的情况:样式改变、换皮肤

INFO

  • 联系:它们都能让元素不可见

  • 区别:

  • display:none;会让元素完全从渲染树中消失,渲染的时候不占据任何空间;visibility: hidden;不会让元素从渲染树消失,渲染师元素继续占据空间,只是内容不可见
  • display: none;是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示;visibility:hidden;是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式
  • 修改常规流中元素的display通常会造成文档重排。修改visibility属性只会造成本元素的重绘
  • 读屏器不会读取display: none;元素内容;会读取visibility: hidden元素内容

面试题:回流与重绘

INFO

  • 当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。

  • 每个页面至少需要一次回流,就是在页面第一次加载的时候。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树。

  • 完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘

面试题:opacity 和 rgba 区别

INFO

  • 共同性:实现透明效果
  • opacity 取值范围0到1之间,0表示完全透明,1表示不透明
  • rgba R表示红色,G表示绿色,B表示蓝色,取值可以在正整数或者百分数。A表示透明度取值0到1之间
  • 区别:继承的区别
  • opacity会继承父元素的opacity属性,而RGBA设置的元素的后代元素不会继承不透明属性。

面试题:::before 和 :after 中双冒号和单冒号 有什么区别?解释一下这 2 个伪元素的作用。

INFO

  • 区别
  • :是伪类、::伪元素 ===》是为了做区分
  • 是什么?作用
  • 元素before之前 、 元素after之后
  • 作用:清除浮动、样式布局上也有作用

面试题:如何关闭 IOS 键盘首字母自动大写

html
<input type="text" autocapitalize="off" />

面试题:怎么让 Chrome 支持小于 12px 的文字?

  • Chrome默认字体大小是:16px
  • 每个浏览器默认字体大小可能都不一样
css
div {
  font-size: 10px;
}
div span {
  display: inline-block;
  -webkit-transform: scale(1.6);
}

面试题:rem 和 em 区别

INFO

  • 相对于font-size

  • em针对于父元素的font-size

  • rem针对于根(html)元素的font-size

面试题:ios 系统中元素被触摸时产生的半透明灰色遮罩怎么去掉

css
a,
button,
input,
textarea {
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

面试题:webkit 表单输入框 placeholder 的颜色值能改变吗?

css
input::-webkit-input-placeholder {
  color: red;
}

面试题:禁止 ios 长按时触发系统的菜单,禁止 ios&android 长按时下载图片

  • 禁止ios 长按时触发系统的菜单,禁止ios&android长按时下载图片
css
html,
body {
  touch-callout: none;
  -webkit-touch-callout: none;

  user-select: none;
  -webkit-user-select: none;
}

面试题:禁止 ios 和 android 用户选中文字

css
html,
body {
  user-select: none;
  -webkit-user-select: none;
}

1.3 JavaScript 基础面试题

面试题:延迟加载 JS 有哪些方式?

  • 延迟加载:asyncdefer
    • 例如:<script defer type="text/javascript" src='script.js'></script>
  • defer: 等html全部解析完成,才会执行js代码,顺次执行js脚本。
  • async: async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)。

面试题:异步加载和延迟加载

  • 异步加载的方案: 动态插入script标签
  • 通过ajax去获取js代码,然后通过eval执行
  • script标签上添加defer或者async属性
  • 创建并插入iframe,让它异步执行js
  • 延迟加载:有些 js 代码并不是页面初始化的时候就立刻需要的,而稍后的某些情况才需要的。

面试题:JS 数据类型有哪些?

INFO

  • 基本类型:string、number、boolean、undefined、null、symbol、bigint

  • 引用类型:Object(Array,Date,RegExp,Function)

  • NaN是一个数值类型,但是不是一个具体的数字。

INFO

  • 基本数据类型:String,Boolean,number,undefined,object,Null
  • 引⽤数据类型:Object(Array,Date,RegExp,Function)

面试题:JS 数组常用方法(至少 6 个)

INFO

  • push
  • pop
  • unshift
  • shift
  • splice
  • join
  • concat
  • forEach
  • filter
  • map
  • sort
  • some
  • every

面试题:JS 数组内置遍历方法有哪些和区别

  • forEach:这个方法是为了取代 for 循环遍历数组的,返回值为 undefined
  • 例如:
javascript
let arrInfo = [4, 6, 6, 8, 5, 7, 87];
arrInfo.forEach((item, index, arr) => {
  //遍历逻辑
});

其中:

  • item代码遍历的每一项,
  • index:代表遍历的每项的索引,
  • arr代表数组本身
  • filter (返回数组):是一个过滤遍历的方法,如果返回条件为 true,则返回满足条件为 true 的新数组
javascript
let arrInfo = [4, 16, 6, 8, 45, 7, 87];
let resultArr = arrInfo.filter((item, index, arr) => {
  //例如返回数组每项值大于9的数组
  return item > 9;
});
console.log(resultArr);
  • map (返回数组):这个 map 方法主要对数组的复杂逻辑处理时用的多,特别是 react 中遍历数据,也经常用到,写法和 forEach 类似
  • map() 方法返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组
  • some (返回 true/false):这个 some 方法用于只要数组中至少存在一个满足条件的结果,返回值就为 true,否则返回 false, 写法和 forEach 类似

  • every (返回 true/false):这个 every 方法用于数组中每一项都得满足条件时,才返回 true,否则返回 false, 写法和 forEach 类似

  • reduce 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值

面试题:find 和 filter 的区别

INFO

  • 区别一:返回的内容不同
    • filter 返回是新数组
    • find 返回具体的内容
  • 区别二:
    • find :匹配到第一个即返回
    • filter : 返回整体(没一个匹配到的都返回)

面试题:some 和 every 的区别

INFO

  • some ==》 如果有一项匹配则返回true
  • every ==》 全部匹配才会返回true

面试题:JS 数据类型考题

考题一:

javascript
console.log(true + 1); //2
console.log(NAN + 1); //NAN
console.log("name" + true); //nametrue
console.log(undefined + 1); //NaN
console.log(typeof undefined); //undefined

考题二:

javascript
console.log(typeof NaN); //number
console.log(typeof null); //object

面试题:null 和 undefined 的区别

INFO

  • 作者在设计js的都是先设计的null(为什么设计了null:最初设计js的时候借鉴了java的语言)
  • null会被隐式转换成0,很不容易发现错误。
  • 先有null后有undefined,出来undefined是为了填补之前的坑。

具体区别:JavaScript的最初版本是这样区分的:null是一个表示"无"的对象(空对象指针),转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。

INFO

我原先看过一些资料 据我所知 作者最先设计出来null 他是借鉴了java语言 但是null有一些问题 比如说:作者会觉得表示”无”的值最好不要是对象,是一个基本类型是最好的 而且null会被隐式转换成0,很不容易发现错误 所有说作者有设计出undefined 因为undefined首先不会隐式转换成0 而且undefined还有一个比较好的点就是它是一个基本类型

面试题:documen.write 和 innerHTML 的区别

INFO

  • document.write只能重绘整个页面
  • innerHTML可以重绘页面的一部分

面试题:JavaScript 里面的作用域有哪些

INFO

  • es6 之前,存在两种
  • 全局作用域
  • 局部作用域(函数作用域)

INFO

  • es6之后,引入一种新的作用域
  • 块级作用域

面试题:== 和 ===有什么不同?

INFO

  • == : 比较的是值
  • string == number || boolean || number ....都会隐式转换
  • 通过valueOf转换(valueOf() 方法通常由 JavaScript 在后台自动调用,并不显式地出现在代码中。)
  • === : 除了比较值,还比较类型

面试题:浏览器从输入 URL 到页面加载的全过程

  • 从输入URL到页面加载的主干流程如下:

INFO

  • 1、浏览器的地址栏输入URL并按下回车。
  • 2、浏览器查找当前URL的DNS缓存记录。
  • 3、DNS解析URL对应的IP。
  • 4、根据IP建立TCP连接(三次握手)
  • 5、HTTP发起请求
  • 6、服务器处理请求,浏览器接收HTTP响应。
  • 7、渲染页面,构建DOM树。
  • 8、关闭TCP连接(四次挥手)

面试题:http 协议的 三次握手/四次挥手,可以描述一下吗? https://www.jianshu.com/p/e5f3c01869ac

INFO

  • http的三次握手和四次挥手:
  • 浏览器在给服,务器传输数据之前,有三次握手,握手成功之后,才可以传输数据
  • 浏览器需要先发送SYN码,客户端请求和服务器建立连接;
  • 服务器接收到SYN码,再发送给客户端SYN+ACK码,我可以建立连接;
  • 客户端接收到ACK码,验证这个ACK是否正确,如果正确则客户端和服务端则建立起数据连接;双方的数据发送通道都将开启;

INFO

  • 四次挥手:
  • 当客户端无数据要传输了,会发送FIN码告诉服务器,我发送完毕了;
  • 当服务器接收完毕后,告诉客户端ACK码,告诉客户端你可以把数据通道关闭了;
  • 当服务器发送完毕之后,也会发送FIN码,告诉浏览器,数据发送完毕;
  • 当客户端接收完毕 之后,同样发送ACK码,告诉服务器,数据接收 完毕,

面试题:事件循环机制(event loop)

INFO

  • js代码执行时,先按代码顺序将同步任务压入主执行栈中执行
  • 遇到异步任务则先将异步任务压入对应的任务队列中(宏队列或微队列)
  • 同步任务执行完毕后,查看微队列,将微任务一一取出进入主执行栈中执行
  • 微任务队列清空后,再查看宏队列,只取出第一个宏任务执行,执行完一个宏任务后,回到第三步的操作 这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)

INFO

事件循环又叫做消息循环,是浏览器渲染主线程的工作方式。在 Chrome 的源码中,它开启一个不会结束的 for 循环,每次循环从消息队列中取出第一个任务执行,而其他线程只需要在合适的时候将任务加入到队列末尾即可。过去把消息队列简单分为宏队列和微队列,这种说法目前已无法满足复杂的浏览器环境,取而代之的是一种更加灵活多变的处理方式。 根据 W3C 官方的解释,每个任务有不同的类型,同类型的任务必须在同一个队列,不同的任务可以属于不同的队列。不同任务队列有不同的优先级,在一次事件循环中,由浏览器自行决定取哪一个队列的任务。但浏览器必须有一个微队列,微队列的任务一定具有最高的优先级,必须优先调度执行。

面试题: 如何理解 JS 的异步?

INFO

JS是一门单线程的语言,这是因为它运行在浏览器的渲染主线程中,而渲染主线程只有一个。而渲染主线程承担着诸多的工作,渲染页面、执行 JS 都在其中运行。如果使用同步的方式,就极有可能导致主线程产生阻塞,从而导致消息队列中的很多其他任务无法得到执行。这样一来,一方面会导致繁忙的主线程白白的消耗时间,另一方面导致页面无法及时更新,给用户造成卡死现象。 所以浏览器采用异步的方式来避免。具体做法是当某些任务发生时,比如计时器、网络、事件监听,主线程将任务交给其他线程去处理,自身立即结束任务的执行,转而执行后续代码。当其他线程完成时,将事先传递的回调函数包装成任务,加入到消息队列的末尾排队,等待主线程调度执行。在这种异步模式下,浏览器永不阻塞,从而最大限度的保证了单线程的流畅运行。

面试题:JS 中的计时器能做到精确计时吗? 为什么?

INFO

  • 不行,因为:
  • 计算机硬件没有原子钟,无法做到精确计时
  • 操作系统的计时函数本身就有少量偏差,由于 JS 的计时器最终调用的是操作系统的函数,也就携带了这些偏差
  • 按照 W3C 的标准,浏览器实现计时器时,如果嵌套层级超过 5 层,则会带有 4 毫秒的最少时间,这样在计时时间少于 4 毫秒时又带来了偏差
  • 受事件循环的影响,计时器的回调函数只能在主线程空闲时运行,因此又带来了偏差

面试题:JS 微任务和宏任务 https://blog.csdn.net/qq_35430000/article/details/88211896

INFO

  • js是单线程的语言。
  • js代码执行流程:同步执行完==》事件循环
  • 同步的任务都执行完了,才会执行事件循环的内容
  • 进入事件循环:请求、定时器、事件....
  • 事件循环中包含:【微任务、宏任务】
  • 微任务:promise.then
  • 宏任务:setTimeout..
  • 要执行宏任务的前提是清空了所有的微任务

  • 流程:同步==》事件循环【微任务和宏任务】==》微任务==》宏任务=》微任务...

INFO

  • 宏任务可以被理解为每次"执⾏栈"中所执⾏的代码,⽽浏览器会在每次宏任务执⾏结束后,在下⼀个宏任务执⾏开始前,对页⾯进⾏渲染,
  • ⽽宏任务包括:
  • script(整体代码)
  • setTimeout
  • setInterval
  • I/O
  • UI交互事件
  • postMessage
  • MessageChannel
  • setImmediate
  • UI rendering

INFO

  • 微任务,可以理解是在当前"执⾏栈"中的任务执⾏结束后⽴即执⾏的任务。⽽且早于页⾯渲染和取任务队列中的任务。
  • 微任务包括:
  • Promise.then
  • Object.observe
  • MutaionObserver
  • process.nextTick

INFO

  • 他们的运⾏机制是这样的:
  • 执⾏⼀个宏任务(栈中没有就从事件队列中获取)
  • 执⾏过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 宏任务执⾏完毕后,⽴即执⾏当前微任务队列中的所有微任务(依次执⾏)
  • 当前宏任务执⾏完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,js线程继续接管,开始下⼀个宏任务(从事件队列中获取)

面试题:JS 作用域考题

INFO

  • 除了函数外,js是没有块级作用域。
  • 作用域链:内部可以访问外部的变量,但是外部不能访问内部的变量。

    注意:如果内部有,优先查找到内部,如果内部没有就查找外部的。

  • 注意声明变量是用var还是没有写(window.)
  • 注意:js有变量提升的机制【变量悬挂声明】
  • 优先级:声明变量 > 声明普通函数 > 参数 > 变量提升

面试的时候怎么看:

INFO

  • 本层作用域有没有此变量【注意变量提升】
  • 注意:js除了函数外没有块级作用域
  • 普通声明函数是不看写函数的时候顺序

面试题:JS 对象考题

JS 对象注意点:

INFO

  • 对象是通过new操作符构建出来的,所以对象之间不想等(除了引用外);
  • 对象注意:引用类型(共同一个地址);
  • 对象的key都是字符串类型;
  • 对象如何找属性|方法;

    查找规则:先在对象本身找 ===> 构造函数中找 ===> 对象原型中找 ===> 构造函数原型中找 ===> 对象上一层原型查找

面试题:JS 判断变量是不是数组,你能写出哪些方法?

方式一:isArray

javascript
var arr = [1, 2, 3];
console.log(Array.isArray(arr));

方式二:instanceof 【可写,可不写】

javascript
var arr = [1, 2, 3];
console.log(arr instanceof Array);

方式三:原型 prototype

javascript
var arr = [1, 2, 3];
console.log(Object.prototype.toString.call(arr).indexOf("Array") > -1);

方式四:isPrototypeOf()

javascript
var arr = [1, 2, 3];
console.log(Array.prototype.isPrototypeOf(arr));

方式五:constructor

javascript
var arr = [1, 2, 3];
console.log(arr.constructor.toString().indexOf("Array") > -1);

面试题:slice 是干嘛的、splice 是否会改变原数组

INFO

  • slice是来截取的
    • 参数可以写slice(3)、slice(1,3)、slice(-3)
    • 返回的是一个新的数组
  • splice 功能有:插入、删除、替换
    • 返回:删除的元素
    • 该方法会改变原数组

面试题:new 操作符具体做了什么

INFO

  • 创建了一个空的对象
  • 将空对象的原型,指向于构造函数的原型
  • 将空对象作为构造函数的上下文(改变this指向)
  • 对构造函数有返回值的处理判断
javascript
function Fun(age, name) {
  this.age = age;
  this.name = name;
}
function create(fn, ...args) {
  //1. 创建了一个空的对象
  var obj = {}; //var obj = Object.create({})
  //2. 将空对象的原型,指向于构造函数的原型
  Object.setPrototypeOf(obj, fn.prototype);
  //3. 将空对象作为构造函数的上下文(改变this指向)
  var result = fn.apply(obj, args);
  //4. 对构造函数有返回值的处理判断
  return result instanceof Object ? result : obj;
}
console.log(create(Fun, 18, "张三"));

面试题:说一下 JS 事件代理(也称事件委托)是什么,及实现原理?

INFO

JS事件代理就是通过给父级元素(例如:ul)绑定事件,不给子级元素(例如:li)绑定事件,然后当点击子级元素时,通过事件冒泡机制在其绑定的父元素上触发事件处理函数,主要目的是为了提升性能,因为我不用给每个子级元素绑定事件,只给父级元素绑定一次就好了,在原生js里面是通过event对象的targe属性实现

javascript
var ul = document.querySelector("ul");
ul.onclick = function (e) {
  //e指event,事件对象
  var target = e.target || e.srcElement; //target获取触发事件的目标(li)
  if (target.nodeName.toLowerCase() == "li") {
    //目标(li)节点名转小写字母,不转的话是大写字母
    alert(target.innerHTML);
  }
};

INFO

jq方式实现相对而言简单 $(“ul”).on(“click”,“li”,function(){//事件逻辑}) 其中第二个参数指的是触发事件的具体目标,特别是给动态添加的元素绑定事件,这个特别起作用

面试题:谈谈 this 的理解

INFO

  • this总是指向函数的直接调用者(而非间接调用者)
  • 如果有new关键字,this指向new出来的那个对象
  • 在事件中,this指向目标元素,特殊的是IE的attachEvent中的this总是指向全局对象window。

面试题:浅谈 setTimeout 和 setInterval、

INFO

  • 前者是在一定时间过后将函数添加至执行队列,执行时间=延迟时间+之前函数代码执行时间+执行函数时间。
  • 后者是不管前一次是否执行完毕,每隔一定时间重复执行,用于精准执行互相没有影响的重复操作。

面试题:闭包

INFO

  • 闭包是什么

    • 闭包是一个函数加上到创建函数的作用域的连接,闭包“关闭”了函数的自由变量。
  • 闭包可以解决什么问题【闭包的优点】

    • 内部函数可以访问到外部函数的局部变量
    • 闭包可以解决的问题
javascript
var lis = document.getElementsByTagName("li");
for (var i = 0; i < lis.length; i++) {
  (function (i) {
    lis[i].onclick = function () {
      alert(i);
    };
  })(i);
}
  • 闭包的缺点

    • 变量会驻留在内存中,造成内存损耗问题。
  • 解决:把闭包的函数设置为null

    • 内存泄漏【ie】 ==> 可说可不说,如果说一定要提到ie

INFO

  • 闭包说的通俗一点就是打通了一条在函数外部访问函数内部作用域的通道。正常情况下函数外部是访问不到函数内部作用域变量的,

  • 表象判断是不是闭包:函数嵌套函数,内部函数被return 内部函数调用外层函数的局部变量

    • 优点:可以隔离作用域,不造成全局污染
    • 缺点:由于闭包长期驻留内存,则长期这样会导致内存泄露
  • 如何解决内存泄露:将暴露全外部的闭包变量置为null

    • 适用场景:封装组件,for循环和定时器结合使用,for循环和dom事件结合.可以在性能优化的过程中,节流防抖函数的使用,导航栏获取下标的使用

面试题:怎么理解 js 中的内存泄露

INFO

  • 定义:程序不需要的内存,由于某些原因其不会返回到操作系统或者可用内存池中。 内存泄露会导致(运行缓慢 ,高延迟,崩溃)的问题
  • 常见的导致内存泄露的原因有:
    • 意外的全局变量
    • 脱离文档的DOM的引用
    • 闭包

面试题:哪些操作会造成内存泄漏?

INFO

  • 内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。

  • 垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。

  • setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏。

  • 闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)

INFO

  • 全局变量、闭包、DOM清空或删除时,事件未清除、子元素存在引用

面试题:什么原型 原型链

原型

原型

原型链:

原型链

面试题:原型链

INFO

  • 原型可以解决什么问题

    • 对象共享属性和共享方法
  • 谁有原型

    • 函数拥有:prototype
    • 对象拥有:__proto__
  • 对象查找属性或者方法的顺序

    • 先在对象本身查找 --> 构造函数中查找 --> 对象的原型 --> 构造函数的原型中 --> 当前原型的原型中查找
  • 原型链

    • 是什么?:就是把原型串联起来
    • 原型链的最顶端是null

面试题:JavaScript 原型,原型链 ? 有什么特点?

INFO

  • 原型对象也是普通的对象,是对象一个自带隐式的 __proto__属性,原型也有可能有自己的原型,如果一个原型对象的原型不为null的话,我们就称之为原型链。

  • 原型链是由一些用来继承和共享属性的对象组成的(有限的)对象链。

面试题:原型链 prototype 和 __proto__ 区别

INFO

  • prototype是函数特有的, __proto__是对象有的

prototype__proto__区别与作用

INFO

prototype把共有属性预先定义好,给之后对象使用 prototype的存在实现了继承,节省内存空间 __proto__是对象的,prototype是函数的,因为函数也是对象,所以函数也有__proto__ __proto__的作用是就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会沿着它的__proto__属性所指向的那个对象(父对象)里找,也就是原型链 prototype的作用是就是让该函数所实例化的对象们都可以找到公用的属性和方法

面试题: JS 继承有哪些方式

方式一:ES6

javascript
class Parent {
  constructor() {
    this.age = 18;
  }
}

class Child extends Parent {
  constructor() {
    super();
    this.name = "张三";
  }
}
let o1 = new Child();
console.log(o1, o1.name, o1.age);

方式二:原型链继承

javascript
function Parent() {
  this.age = 20;
}
function Child() {
  this.name = "张三";
}
Child.prototype = new Parent();
let o2 = new Child();
console.log(o2, o2.name, o2.age);

方式三:借用构造函数继承

javascript
function Parent() {
  this.age = 22;
}
function Child() {
  this.name = "张三";
  Parent.call(this);
}
let o3 = new Child();
console.log(o3, o3.name, o3.age);

方式四:组合式继承

javascript
function Parent() {
  this.age = 100;
}
function Child() {
  Parent.call(this);
  this.name = "张三";
}
Child.prototype = new Parent();
let o4 = new Child();
console.log(o4, o4.name, o4.age);

面试题:说一下 call、apply、bind 区别

  • 共同点:功能一致

INFO

  • 可以改变this指向

  • 语法: 函数.call()、函数.apply()、函数.bind()

  • 区别:

INFO

  • call、apply可以立即执行。bind不会立即执行,因为bind返回的是一个函数需要加入()执行。
  • 参数不同:apply第二个参数是数组。call和bind有多个参数需要挨个写。

INFO

  • 面试时候说:

    • call、apply、bind功能都是改变函数体内的this指向的
  • 他们的区别是

    • 1.call、apply可以立即执行 bind不会立即执行,因为bind返回的是一个函数需要加入()执行
    • 2.参数不同:apply第二个参数是数组 call和bind有多个参数 可能又三四个 五六个 需要挨个写
    • 3.使用场景:一般情况用call就可以了 但是在特定情况下 可能我会用apply 比如: Math.max.apply 因为max后面是一个一个值 但是可能取最大值 他是一个数组,正好apply第二参数是数组 这就没问题 用call就不行 用bind 情况下我们可能是用函数 比如你要给某一个dom元素加入一个onclick事件 但是你希望赋值的元素体指向某一个元素 这时候就可以用bind
  • 场景:
  • 用apply的情况
javascript
var arr1 = [1, 2, 4, 5, 7, 3, 321];
console.log(Math.max.apply(null, arr1));
  • 用bind的情况
javascript
var btn = document.getElementById("btn");
var h1s = document.getElementById("h1s");
btn.onclick = function () {
  console.log(this.id);
}.bind(h1s);

面试题:sort 背后原理是什么?

INFO

面试题:深拷贝和浅拷贝

  • 共同点:复制

  • 浅拷贝:只复制引用,而未复制真正的值。

javascript
var arr1 = ["a", "b", "c", "d"];
var arr2 = arr1;
  • 深拷贝:是复制真正的值 (不同引用)
javascript
var obj3 = {
  a: 1,
  b: 2,
};
var obj4 = JSON.parse(JSON.stringify(obj3));

//递归的形式
function copyObj(obj) {
  if (Array.isArray(obj)) {
    var newObj = [];
  } else {
    var newObj = {};
  }
  for (var key in obj) {
    if (typeof obj[key] == "object") {
      newObj[key] = copyObj(obj[key]);
    } else {
      newObj[key] = obj[key];
    }
  }
  return newObj;
}
console.log(copyObj(obj5));

面试题:JSON.parse(JSON.stringify(obj))缺点

INFO

  • 如果json里面有时间对象,则序列化后会将时间对象转换为字符串格式
  • 如果json里有 function,undefined,则序列化后会将 function,undefined 丢失
  • 如果json里有NaNInfinity-Infinity,则序列化后会变成null
  • 如果json里有对象是由构造函数生成的,则序列化的结果会丢弃对象的 constructor
  • 如果对象中存在循环引用的情况将抛出错误
  • 当json里有RegExpError对象时,序列化的结果将只得到一个空对象;

面试题:localStorage、sessionStorage、cookie 的区别

  • 公共点:在客户端存放数据

  • 区别

INFO

  • 数据存放有效期

    • sessionStorage : 仅在当前浏览器窗口关闭之前有效。【关闭浏览器就没了】
    • localStorage : 始终有效,窗口或者浏览器关闭也一直保存,所以叫持久化存储。
    • cookie: 只在设置的cookie过期时间之前有效,即使窗口或者浏览器关闭也有效。
  • localStoragesessionStorage不可以设置过期时间

    • cookie 有过期时间,可以设置过期(把时间调整到之前的时间,就过期了)
  • 存储大小的限制

    • cookie存储量不能超过4k
    • localStoragesessionStorage不能超过5M
  • cookie根据不同的浏览器存储的大小是不同的。

面试题:ajax 过程

INFO

  • 创建XMLHttpRequest对象,也就是创建一个异步调用对象.

  • 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.

  • 设置响应HTTP请求状态变化的函数.

  • 发送HTTP请求.

  • 获取异步调用返回的数据.

  • 使用JavaScript和DOM实现局部刷新.

面试题:GET 和 POST 的区别,何时使用 POST?

INFO

  • GET:一般用于信息获取,使用URL传递参数,对所发送信息的数量也有限制,一般在2000个字符

  • POST:一般用于修改服务器上的资源,对所发送的信息没有限制。

  • GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值,也就是说Get是通过地址栏来传值,而Post是通过提交表单来传值。

  • 然而,在以下情况中,请使用 POST 请求:

    • 无法使用缓存文件(更新服务器上的文件或数据库)
    • 向服务器发送大量数据(POST 没有数据量限制)
    • 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

面试题:http 状态码有那些?分别代表是什么意思?列举 2-3 个熟悉的状态码

INFO

  • 当用户在浏览网页的时候,浏览器会返回一个htttp状态码,主要是用来响应浏览器的请求。

  • 200 OK 请求正常处理完毕

  • 204 No Content 请求成功处理,没有实体的主体返回

  • 301 Moved Permanently 永久重定向,资源已永久分配新URI

  • 302 Found 临时重定向,资源已临时分配新URI

  • 400 Bad Request 请求报文语法错误或参数错误

  • 401 Unauthorized 要通过HTTP认证,或认证失败

  • 403 Forbidden 请求资源被拒绝

  • 404 Not Found 无法找到请求资源(服务器无理由拒绝)

  • 500 Internal Server Error 服务器故障或Web应用故障

  • 503 Service Unavailable 服务器超负载或停机维护你可以关闭;

面试题: map 、 set 、 哈希表 区别

  • map和object区别是

    • object对象存储的key都是字符串类型
    • map的key可以接受任何类型
  • map和哈希表区别是

    • 哈希表又叫散列表
    • 区别:如果要找到对象的某一个值,哈希表省去了遍历的过程和操作

INFO

  • Map是键值对,Set是值的集合,键和值可以是任何的值;

  • Map可以通过get方法获取值,而set不能因为它只有值,set只能用has来判断,返回一个布尔值;

  • Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储

面试题: BOM 是指什么

  • 浏览器对象模型

面试题:BOM 和 DOM 的区别

INFO

  • BOM是浏览器对象模型,用来获取或设置浏览器的属性、行为,例如:新建窗口、获取屏幕分辨率、浏览器版本号等。

  • DOM是文档对象模型,用来获取或设置文档中标签的属性,例如获取或者设置input表单的value值。

  • BOM的内容不多,主要还是DOM。

  • 由于DOM的操作对象是文档(Document),所以dom和浏览器没有直接关系

面试题: BOM 常用方法有什么

  • 弹窗

INFO

  • window.alert
  • window.confirm
  • window.prompt
  • 定时器

INFO

  • 定时器
  • 只执行一次 - setTimeout
  • 重复执行 - setInterval
  • location 对象

INFO

  • 端口: ${location.port}
    • 协议: ${location.protocol}
    • 主机地址(带端口): ${location.host}
    • 主机地址(不带端口): ${location.hostname}
    • 访问的主机内路径: ${location.pathname}
    • 地址栏的完整地址: ${location.href}
    • 查询参数: ${location.search}
  • 常用方法
    • 页面跳转(会保存历史记录) location.href
    • 页面跳转(不保存历史记录) location.replace
    • 页面重载 location.reload
  • navigator 对象

INFO

  • 对象内存储了用户浏览器信息和系统信息。但不是很准确具有一定误导性
  • 用户浏览器是否开启cookies: navigator.cookieEnabled
  • 用户浏览器本地语言:navigator.language
  • 用户代理(浏览器信息, 系统信息等):navigator.userAgent
  • history 对象

INFO

  • back: 对应浏览器中的回退按钮 history.back();
  • forward: 对应浏览器中的前进按钮 history.forward();
  • go: 参数为正数时等同于 back 效果, 为负数时等同于 forward 效果
  • 后退 history.go(-1);
  • 前进 history.go(1);

面试题:BOM 获取浏览器唯一标识

  • navigator.userAgent

第二章 面试题进阶篇

2.1 ES6 面试题

面试题:varletconst 区别

  • varletconst 共同点都是可以声明变量的

  • 区别一

INFO

  • var 具有变量提升的机制
  • letconst没有变量提升的机制
  • 区别二:

INFO

  • var 可以多次声明同一个变量
  • letconst不可以多次声明同一个变量
  • 区别三:

INFO

  • var、let`声明变量的

  • const声明常量

  • varlet声明的变量可以再次赋值,但是const不可以再次赋值了。

  • 区别四:

INFO

  • var声明的变量没有自身作用域
  • letconst声明的变量有自身的作用域

面试题:作用域考题

考题一:let 和 const 没有变量提升性

javascript
console.log(str); //undefined
var str = "你好";

console.log(num); //报错
let num = 10;

考题二:

javascript
function demo() {
  var n = 2;
  if (true) {
    var n = 1;
  }
  console.log(n); //1
}
demo();

function demo() {
  let n = 2;
  if (true) {
    let n = 1;
  }
  console.log(n); //2
}
demo();

考题三:可以修改

javascript
const obj = {
  a: 1,
};
obj.a = 11111;
console.log(obj);

const arr = ["a", "b", "c"];
arr[0] = "aaaaa";
console.log(arr);

面试题:将下列对象进行合并

方式一:Object.assign

javascript
const a = { a: 1, b: 4 };
const b = { b: 2, c: 3 };

let obj1 = Object.assign(a, b);
console.log(obj1);

方式二:...

javascript
let obj2 = { ...a, ...b };
console.log(obj2);

方式三:自己封装方法

javascript
function extend(target, source) {
  for (var key in source) {
    target[key] = source[key];
  }
  return target;
}
console.log(extend(a, b));

面试题:箭头函数和普通函数有什么区别?

INFO

  • this指向的问题
    • 箭头函数中的this只在箭头函数定义时就决定的,而且不可修改的(call、apply、bind)
    • ****箭头函数的this指向定义时候、外层第一个普通函数的this
  • 箭头函数不能new(不能当作构造函数)
  • 箭头函数prototype
  • 箭头函数arguments
  • 面试时候说:

INFO

  • this指向的问题
  • 首先this指向的箭头函数是不可通过(call、apply、bind)修改的 它的this就在定义时就决定的 而且取决于他外层第一个普通函数的this 其次箭头函数不能new操作符进行实力话 也就说不能当作一个构造函数 其次箭头函数没有原型 还有箭头函数没有arguments对象

面试题:typeofinstanceof 的区别

  • 相同点:

INFO

  • JavaScript 中 typeofinstanceof 常用来判断一个变量是否为空, 或者是什么类型的。
  • 不同点:

INFO

  • typeof:

    • 返回值是一个字符串, 用来说明变量的数据类型。 2、typeof 一般只能返回如下几个结果:number, boolean, string, function, object, undefined。 对于 Array, Null 等特殊对象使用 typeof 一律返回 object, 这正是 typeof 的局限性
  • instanceof

    • 返回值为布尔值
    • instanceof 用于判断一个变量是否属于某个对象的实例。

面试题:isNaN 和 Number.isNaN 区别

  • isNaN会将参数做类型转换后再判断
  • Number.isNaN 不会做类型转换,判断不是数字类型即返回false

面试题:防抖、节流

  • 防抖动和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。

  • 防抖(debounce)

INFO

指在时间n内,函数被触发多次,但是只执行一次,执行最新的触发。也就是在时间n内,碰到新的触发,就清除之前的,重新计时。

javascript
function debounce(func, ms = 1000) {
  let timer;
  return function (...args) {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      func.apply(this, args);
    }, ms);
  };
}

// 测试
const task = () => {
  console.log("run task");
};
const debounceTask = debounce(task, 1000);
window.addEventListener("scroll", debounceTask);
  • 节流(throttle)

INFO

当持续触发某个事件时,会有规律的每隔时间n就执行一次函数。

javascript
function throttle(func, ms = 1000) {
  let canRun = true;
  return function (...args) {
    if (!canRun) return;
    canRun = false;
    setTimeout(() => {
      func.apply(this, args);
      canRun = true;
    }, ms);
  };
}

// 测试
const task = () => {
  console.log("run task");
};
const throttleTask = throttle(task, 1000);
window.addEventListener("scroll", throttleTask);

面试题:Promise 有几种状态

  • 有三种状态:

INFO

  • pending(进行中)
  • fulfilled(已成功)
  • rejected(已失败)
  • 在Promise的内部,有一个状态管理器的存在,有三种状态:pending、fulfilled、rejected。

INFO

  • promise 对象初始化状态为 pending。
  • 当调用resolve(成功),会由pending => fulfilled。
  • 当调用reject(失败),会由pending => rejected。
  • 需要记住的是注意promsie状态 只能由 pending => fulfilled/rejected, 一旦修改就不能再变。

面试题:promise 常用方法

INFO

  • resolve 返回一个由参数决定的Promise对象,简单来说就是返回一个Promise对象,且是成功的时候调用该方法,会将信息传递给下一个then方法。

  • reject 返回一个状态为失败的Promise对象,并将失败信息传递给对应的catch方法

  • all 把封装好的Promise方法进行链式调用

  • Promise.all方法必须是所有的对象都是调用成功的resolve方法,否则会走catch方法。然后得到的结果会按顺序输出一个数组。如果参数不是Promise对象,这些值会被忽略,但是结果放入数组。在对于页面一些必须所有数据得到才渲染的场景下,all方法非常有用

  • race 第一个执行完毕的结果,无论结果是成功还是失败

  • Promise.finally是无论Promise最后是fulfilled还是rejected都会执行的操作。

面试题:promise和async await的区别是什么?

INFO

  • 都是处理异步请求的方式
  • promise是ES6,async await 是ES7的语法
  • async await是基于promise实现的,他和promise都是非阻塞性的
  • 优缺点:

INFO

  • promise是返回对象我们要用then,catch方法去处理和捕获异常,并且书写方式是链式,容易造成代码重叠,不好维护,async await 是通过tra catch进行捕获异常
  • async await最大的优点就是能让代码看起来像同步一样,只要遇到await就会立刻返回结果,然后再执行后面的操作 promise.then()的方式返回,会出现请求还没返回,就执行了后面的操作

面试题:import 和 require 的区别 https://zhuanlan.zhihu.com/p/121770261

INFO

  • import和require都是被模块化使用
  • require是运行时调用,所以可以随处引入
  • import是编译时调用,必须放在文件开头引入,目前部分浏览器不支持,需要用babel把es6转成es5再执行说

2.2 webpack 面试题

面试题:webpack 插件 https://www.cnblogs.com/gaoht/p/11310365.html

面试题:webpack 的作用是什么,谈谈你对它的理解

现在的前端网页功能丰富,特别是SPA(single page web application 单页应用)技术流行后,JavaScript的复杂度增加和需要一大堆依赖包,还需要解决Scss,Less……新增样式的扩展写法的编译工作。
所以现代化的前端已经完全依赖于webpack的辅助了。
现在最流行的三个前端框架,可以说和webpack已经紧密相连,框架官方都推出了和自身框架依赖的webpack构建工具。

react.js+WebPack
vue.js+WebPack
AngluarJS+WebPack

面试题:webpack 的工作原理

WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。在3.0出现后,Webpack还肩负起了优化项目的责任。

面试题:webpack 打包原理

把一切都视为模块:不管是 css、JS、Image 还是 html 都可以互相引用,通过定义 entry.js,对所有依赖的文件进行跟踪,将各个模块通过 loader 和 plugins 处理,然后打包在一起。
按需加载:打包过程中 Webpack 通过 Code Splitting 功能将文件分为多个 chunks,还可以将重复的部分单独提取出来作为 commonChunk,从而实现按需加载。把所有依赖打包成一个 bundle.js 文件,通过代码分割成单元片段并按需加载

面试题:webpack 的核心概念

Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。告诉webpack要使用哪个模块作为构建项目的起点,默认为./src/index.js

output :出口,告诉webpack在哪里输出它打包好的代码以及如何命名,默认为./dist

Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。

Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。

Loader:模块转换器,用于把模块原内容按照需求转换成新内容。

Plugin:扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。

面试题:Webpack 的基本功能有哪些

代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等

文件优化:压缩 JavaScript、CSS、html 代码,压缩合并图片等

代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载

模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件

自动刷新:监听本地源代码的变化,自动构建,刷新浏览器

代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过

自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。

面试题:webpack 是解决什么问题而生的

如果像以前开发时一个html文件可能会引用十几个js文件,而且顺序还不能乱,因为它们存在依赖关系,同时对于ES6+等新的语法,less, sass等CSS预处理都不能很好的解决……,此时就需要一个处理这些问题的工具。

面试题:webpack 与 grunt、gulp 的不同

三者都是前端构建工具,grunt和gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。

grunt和gulp是基于任务和流(Task、Stream)的。类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。

webpack是基于入口的。webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。

所以总结一下:

从构建思路来说
gulp和grunt需要开发者将整个前端构建过程拆分成多个`Task`,并合理控制所有`Task`的调用关系 webpack需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader做何种解析和加工

对于知识背景来说
gulp更像后端开发者的思路,需要对于整个流程了如指掌 webpack更倾向于前端开发者的思路

面试题:与 webpack 类似的工具还有哪些?谈谈你为什么最终选择(或放弃)使用 webpack

同样是基于入口的打包工具还有以下几个主流的:
    webpack
    rollup
    parcel
从应用场景上来看:
    webpack适用于大型复杂的前端站点构建
    rollup适用于基础库的打包,如vue、react
    parcel适用于简单的实验性项目,他可以满足低门槛的快速看到效果
    由于parcel在打包过程中给出的调试信息十分有限,所以一旦打包出错难以调试,所以不建议复杂的项目使用parcel

面试题:有哪些常见的 Loader?他们是解决什么问题的?

file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
source-map-loader:加载额外的 Source Map 文件,以方便断点调试
image-loader:加载并且压缩图片文件
babel-loader:把 ES6 转换成 ES5
css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。
eslint-loader:通过 ESLint 检查 JavaScript 代码
css-loader读取 合并CSS 文件
style-loader把 CSS 内容注入到 JavaScript 里
sass-loader 解析sass文件(安装sass-loader,node-sass)
postcss-loader自动添加浏览器兼容前缀(postcss.config配置)
url-loader将文件转换为base64 URI。
vue-loader处理vue文件。

面试题:Loader 机制的作用是什么?

webpack默认只能打包js文件,配置里的module.rules数组配置了一组规则,告诉 Webpack 在遇到哪些文件时使用哪些 Loader 去加载和转换打包成js。
注意:
use属性的值需要是一个由 Loader 名称组成的数组,Loader 的执行顺序是由后到前的;
每一个 Loader 都可以通过 URL querystring 的方式传入参数,例如css-loader?minimize中的minimize告诉css-loader要开启 CSS 压缩。

面试题:有哪些常见的 Plugin?他们是解决什么问题的?

define-plugin:定义环境变量
commons-chunk-plugin:提取公共代码
uglifyjs-webpack-plugin:插件用来缩小(压缩优化)js文件
HtmlWbpackPlugin自动在打包结束后生成html文件,并引入bundle.js
clearwebPackPlugin打包自动删除上次打包文件
mini-css-extract-plugin 提取CSS到一个单独的文件中
copy-webpack-plugin 复制文件或目录到执行区域,如vue的打包过程中,如果我们将一些文件放到public的目录下,那么这个目录会被复制到dist文件夹中

面试题:Plugin(插件)的作用是什么

Plugin 是用来扩展 Webpack 功能的,通过在构建流程里注入钩子实现,它给 Webpack 带来了很大的灵活性。
Webpack 是通过plugins属性来配置需要使用的插件列表的。plugins属性是一个数组,里面的每一项都是插件的一个实例,在实例化一个组件时可以通过构造函数传入这个组件支持的配置属性。

面试题:ExtractTextPlugin 插件的作用

ExtractTextPlugin插件的作用是提取出 JavaScript 代码里的 CSS 到一个单独的文件。
对此你可以通过插件的filename属性,告诉插件输出的 CSS 文件名称是通过[name]_[contenthash:8].css字符串模版生成的,里面的[name]代表文件名称,[contenthash:8]代表根据文件内容算出的8位 hash 值, 还有很多配置选项可以在ExtractTextPlugin的主页上查到。

面试题:Loader 和 Plugin 的不同?

不同的作用

Loader直译为"加载器"。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以Loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。

Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

不同的用法

Loader在module.rules中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个Object,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options)

Plugin在plugins中单独配置。 类型为数组,每一项是一个plugin的实例,参数都通过构造函数传入。

面试题:什么是 bundle,什么是 chunk,什么是 module

bundle:是由webpack打包出来的文件
chunk:是指webpack在进行模块依赖分析的时候,代码分割出来的代码块
module:是开发中的单个模块

面试题:前端为什么要进行打包和构建

代码层面:
    体积更小(Tree-shaking、压缩、合并),加载更快
    编译高级语言和语法(TS、ES6、模块化、scss)
    兼容性和错误检查(polyfill,postcss,eslint)
研发流程层面:
    统一、高效的开发环境
    统一的构建流程和产出标准
    集成公司构建规范(提测、上线)

面试题:webpack 的构建流程是什么?从读取配置到输出文件这个过程尽量说全

Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:

    初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;

    开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;

    确定入口:根据配置中的 entry 找出所有的入口文件;

    编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;

    完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;

    输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;

    输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。

面试题:怎么配置单页应用?怎么配置多页应用?

单页应用可以理解为webpack的标准模式,直接在entry中指定单页应用的入口即可,这里不再赘述

多页应用的话,可以使用webpack的 AutoWebPlugin来完成简单自动化的构建,但是前提是项目的目录结构必须遵守他预设的规范。 多页应用中要注意的是:

    每个页面都有公共的代码,可以将这些代码抽离出来,避免重复的加载。比如,每个页面都引用了同一套css样式表

    随着业务的不断扩展,页面可能会不断的追加,所以一定要让入口的配置足够灵活,避免每次添加新页面还需要修改构建配置

面试题:是否写过 Loader 和 Plugin?描述一下编写 loader 或 plugin 的思路

Loader像一个"翻译官"把读到的源文件内容转义成新的文件内容,并且每个Loader通过链式操作,将源文件一步步翻译成想要的样子。

编写Loader时要遵循单一原则,每个Loader只做一种"转义"工作。 每个Loader的拿到的是源文件内容(source),可以通过返回值的方式将处理后的内容输出,也可以调用this.callback()方法,将内容返回给webpack。 还可以通过 this.async()生成一个callback函数,再用这个callback将处理后的内容输出出去。 此外webpack还为开发者准备了开发loader的工具函数集——loader-utils。

相对于Loader而言,Plugin的编写就灵活了许多。 webpack在运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

面试题:如何利用 webpack 来优化前端性能?(提高性能和体验)

用webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运行快速高效。

    压缩代码。删除多余的代码、注释、简化代码的写法等等方式。可以利用webpack的UglifyJsPlugin和ParallelUglifyPlugin来压缩JS文件, 利用cssnano(css-loader?minimize)来压缩css

    利用CDN加速。在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对于output参数和各loader的publicPath参数来修改资源路径

    删除死代码(Tree Shaking)。将代码中永远不会走到的片段删除掉。可以通过在启动webpack时追加参数--optimize-minimize来实现

    提取公共代码。

面试题:如何提高 webpack 的构建速度?

多入口情况下,使用CommonsChunkPlugin来提取公共代码

通过externals配置来提取常用库

利用DllPlugin和DllReferencePlugin预编译资源模块 通过DllPlugin来对那些我们引用但是绝对不会修改的npm包来进行预编译,再通过DllReferencePlugin将预编译的模块加载进来。

使用Happypack 实现多线程加速编译

使用webpack-uglify-parallel来提升uglifyPlugin的压缩速度。 原理上webpack-uglify-parallel采用了多核并行压缩来提升压缩速度

使用Tree-shaking和Scope Hoisting来剔除多余代码

面试题:npm 打包时需要注意哪些?如何利用 webpack 来更好的构建?

Npm是目前最大的 JavaScript 模块仓库,里面有来自全世界开发者上传的可复用模块。你可能只是JS模块的使用者,但是有些情况你也会去选择上传自己开发的模块。 关于NPM模块上传的方法可以去官网上进行学习,这里只讲解如何利用webpack来构建。

NPM 模块需要注意以下问题:

    要支持CommonJS模块化规范,所以要求打包后的最后结果也遵守该规则。

    Npm模块使用者的环境是不确定的,很有可能并不支持ES6,所以打包的最后结果应该是采用ES5编写的。并且如果ES5是经过转换的,请最好连同SourceMap一同上传。

    Npm包大小应该是尽量小(有些仓库会限制包大小)

    发布的模块不能将依赖的模块也一同打包,应该让用户选择性的去自行安装。这样可以避免模块应用者再次打包时出现底层模块被重复打包的情况。

   UI组件类的模块应该将依赖的其它资源文件,例如.css文件也需要包含在发布的模块里。

基于以上需要注意的问题,我们可以对于 webpack 配置做以下扩展和优化:

CommonJS模块化规范的解决方案: 设置output.libraryTarget='commonjs2'使输出的代码符合CommonJS2 模块化规范,以供给其它模块导入使用 输出ES5代码的解决方案:使用babel-loader把 ES6 代码转换成 ES5 的代码。再通过开启devtool: 'source-map'输出SourceMap以发布调试。 Npm包大小尽量小的解决方案:Babel 在把 ES6 代码转换成 ES5 代码时会注入一些辅助函数,最终导致每个输出的文件中都包含这段辅助函数的代码,造成了代码的冗余。解决方法是修改.babelrc文件,为其加入transform-runtime插件 不能将依赖模块打包到NPM模块中的解决方案:使用externals配置项来告诉webpack哪些模块不需要打包。 对于依赖的资源文件打包的解决方案:通过css-loader和extract-text-webpack-plugin来实现,配置如下:

img

面试题:如何在 vue 项目中实现按需加载?

INFO

Vue UI组件库的按需加载 为了快速开发前端项目,经常会引入现成的UI组件库如ElementUI、iView等,但是他们的体积和他们所提供的功能一样,是很庞大的。 而通常情况下,我们仅仅需要少量的几个组件就足够了,但是我们却将庞大的组件库打包到我们的源码中,造成了不必要的开销。

INFO

不过很多组件库已经提供了现成的解决方案,如Element出品的babel-plugin-component和AntDesign出品的babel-plugin-import 安装以上插件后,在.babelrc配置中或babel-loader的参数中进行设置,即可实现组件按需加载了。

img

INFO

单页应用的按需加载 现在很多前端项目都是通过单页应用的方式开发的,但是随着业务的不断扩展,会面临一个严峻的问题——首次加载的代码量会越来越多,影响用户的体验。

通过import()语句来控制加载时机,webpack内置了对于import()的解析,会将import()中引入的模块作为一个新的入口在生成一个chunk。 当代码执行到import()语句时,会去加载Chunk对应生成的文件。import()会返回一个Promise对象,所以为了让浏览器支持,需要事先注入Promise polyfill

面试题:sourceMap


是一个映射关系,将打包后的文件隐射到源代码,用于定位报错位置
配置方式:
例如:devtool:‘source-map’
加不同前缀意义:
inline:不生成映射关系文件,打包进main.js

    cheap: 1.只精确到行,不精确到列,打包速度快 2.只管业务代码,不管第三方模块

    module:不仅管业务代码,而且管第三方代码

    eval:执行效率最快,性能最好

最佳实践:
开发环境:cheap-module-eval-source-map
线上环境:cheap-mudole-source-map

面试题:HMR 热模块更新


借助webpack.HotModuleReplacementPlugin(),devServer开启hot
场景1:实现只刷新css,不影响js
场景2:js中实现热更新,只更新指定js模块
js
if (module.hot) {
  module.hot.accept(’./library.js’, function() {
    // Do something with the updated library module…
  });
}

面试题:webpack 如何配置多入口文件?

js
entry: {
 home: resolve(__dirname, "src/home/index.js"),
 about: resolve(__dirname, "src/about/index.js")
}

用于描述入口的对象。你可以使用如下属性:

dependOn: 当前入口所依赖的入口。它们必须在该入口被加载前被加载。

filename: 指定要输出的文件名称。

import: 启动时需加载的模块。

library: 指定 library 选项,为当前 entry 构建一个 library。

runtime: 运行时 chunk 的名字。如果设置了,就会创建一个新的运行时 chunk。在 webpack 5.43.0 之后可将其设为 false 以避免一个新的运行时 chunk。

publicPath: 当该入口的输出文件在浏览器中被引用时,为它们指定一个公共 URL 地址

面试题:什么是模热更新?有什么优点?

模块热更新是webpack的一个功能,它可以使得代码修改之后,不用刷新浏览器就可以更新。

在应用过程中替换添加删出模块,无需重新加载整个页面,是高级版的自动刷新浏览器。

优点:只更新变更内容,以节省宝贵的开发时间。调整样式更加快速,几乎相当于在浏览器中更改样式

面试题:lazy loading(模块懒加载)

借助import()语法异步引入组件,实现文件懒加载:prefetch,preloading
webpack提倡多写异步代码,提升代码利用率,从而提升页面性能
先加载主业务文件,prefetch利用网络空闲时间,异步加载组件

import(/* webpackPrefetch: true / ‘LoginModal’);
preload和主业务文件一起加载,异步加载组件

import(/ webpackPreload: true */ ‘ChartingLibrary’);

面试题:什么是长缓存?在 webpack 中如何做到长缓存优化?

浏览器在用户访问页面的时候,为了加快加载速度,会对用户访问的静态资源进行存储,但是每一次代码升级或者更新,都需要浏览器去下载新的代码,最方便和最简单的更新方式就是引入新的文件名称。

在webpack中,可以在output给出输出的文件制定chunkhash,并且分离经常更新的代码和框架代码,通过NameModulesPlugin或者HashedModulesPlugin使再次打包文件名不变。

面试题:什么是 Tree-sharking

指打包中去除那些引入了但在代码中没用到的死代码。在wepack中js treeshaking通过UglifyJsPlugin来进行,css中通过purify-CSS来进行。

面试题:webpack-dev-server 和 http 服务器的区别

webpack-dev-server使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,比传统的http服务对开发更加有效。

面试题:webpack3 和 webpack4 的区别

mode/–mode参数,新增了mode/–mode参数来表示是开发还是生产(development/production)production 侧重于打包后的文件大小,development侧重于goujiansud移除loaders,必须使用rules(在3版本的时候loaders和rules 是共存的但是到4的时候只允许使用rules)移除了CommonsChunkPlugin (提取公共代码),用optimization.splitChunks和optimization.runtimeChunk来代替支持es6的方式导入JSON文件,并且可以过滤无用的代码

2.3 Git 面试题

面试题:git 常用命令

测试是否安装成功

sh
 git --version

克隆线上项目

sh
git clone "地址"

初始化仓库

sh
git init

Git 全局设置

sh
git config --global user.name "用户名"
git config --global user.email "邮箱"

Git 局部配置

sh
git config  user.name "用户名"
git config  user.email "邮箱"

查看全局配置信息

sh
git config --global --list

查看局部配置信息

sh
git config -l

查看状态

sh
git status
    红色的===》没有被git管理
    绿色的===》存储在版本库暂缓区

添加到暂缓区

sh
git add .
    ****.代表所有文件
    ****指定某一个文件 git add index.js

添加到分支中

sh
git commit -m '注释内容'

拉取显示内容

sh
git pull

提交

sh
git push

查看修改文件

sh
git diff
    ****查看某一个文件:git diff index.js
    ****查看所有文件  :git diff

查看修改历史

sh
git log
git reflog (简单形式)

回到之前的版本

sh
回到上一个版本:git reset --hard HEAD^
回到指定版本  :git reset --hard 版本号

面试题:git 分支的操作

修改 git 源

INFO

新建分支

sh
git branch 分支名称

切换分支

sh
 git checkout 分支名称

刷新分支

sh
git remote update origin --prune

查看远程仓库的分支

sh
git branch -r

查看本地分支

sh
git branch

查看本地分支所关联的远程分支

sh
git branch -vv

本地分支提交到远程仓库

sh
git push --set-upstream origin 分支名称

删除本地分支

sh
git branch -d 分支名称

删除远程仓库的分支

sh
 git push origin --delete 分支名称

合并分支

sh
 git merge 分支名称
    注意:如果当前是在master分支下写入:git merge dev,那么master和dev会进行合并,相当于master + dev

配置 SSH 公钥 设置-》SSH 公钥

sh
终端运行:ssh-keygen -t rsa -C "邮箱"
cat ~/.ssh/id_rsa.pub //把运行后的代码复制粘贴到【SSH公钥】配置中

面试题:解决冲突

  • 我们必须先把远程仓库的代码下拉,然后再push

面试题:GitFlow

INFO

  • gitflow (中、大型)
  • master 用于保存上线版本代码,创建了dev分支
  • develop 用于保存相对稳定版本的代码,所有的feature都是dev分支创建的
  • feature 用于开发某几个功能,不同的功能可能会创建不同的分支
  • feature/login
  • feature/list
  • release 用于代码上线前的准备(测试,bug修复),是dev创建的
  • release/v1.0
  • bugfix 用于修复不紧急bug
  • hotfix 用于修复紧急bug

面试题:git 有冲突面试怎么说

INFO

git 有冲突 是两个人协商 找到冲突点 git 里面有冲突提示 看看谁改 改完之后确保没有冲突 然后再次提交

面试题:说一下多人操作同一个文件,如果出现冲突该如何解决

INFO

当遇到多人协作修改同一个文件时出现冲突,我先将远程文件先 git pull 下来,手动修改冲突代码后,再 git add ,git commit,git push 再上传到远程仓库。如果 pull 也 pull 不下来提示冲突的话,可以先通过 git stash 暂存下来,然后再 pull 拉取,然后 git stash pop,取出原来写的,手动修改,然后提交

2.4 正则

什么是正则

  • 规则表达式

应用场景

  • 表单验证

正则使用

INFO

  • 定义:

    • 字面量 //
    • 构造函数:new RegExp()
  • 区别:

    • new RegExp()可以放变量
    • 字面量不可以

方法

  • test() 检测一个内容是否与正则匹配 匹配返回true 不匹配false
  • exec() 检测一个内容是否与正则匹配 匹配返回数组 不匹配null

正则修饰符

  • g : 全文匹配
  • i : 不分区大小写
  • m : 换行(不常用)

限定符

  • ^ 开始
  • $ 结束

分组

  • () 把部分内容组合在一起

字符类(获取分组内的内容)

javascript
$1

$2

$3
...

运行前提 正则必须执行一次

例如:

  var str = '2021-06-25';

  var reg = /^(\d{4})-(\d{2})-(\d{2})$/;

  console.log(str.replace(reg,'$1'))

  //或者

  reg.test(str)或者 reg.exec(str)

  console.log(RegExp.$1,RegExp.$2,RegExp.$3)

重复

INFO

  • 重复最少0次 最多不限
  • + 重复最少一次 最多不限
  • ?重复最少0次 最多一次
  • {n} 重复n次
  • {n,m} 最少重复n次 最多不限
  • {n,} 最少重复n次 最多不限

元字符 (http://c.biancheng.net/view/5632.html)

INFO

  • [] 匹配括号内任意一个
  • [^] 除了括号内任意字符
  • [0-9] 匹配0-9范围
  • [a-z] 匹配小写a-z
  • [A-Z] 匹配大写A-Z
  • [^a-z] 匹配任何不在指定范围内的任意字符
  • [a-zA-Z0-9] 匹配大小写 数字
  • \d 匹配数字
  • \D 匹配非数字
  • \w 匹配数字字母下划线
  • \W 匹配非数字字母下划线
  • \s 匹配空格
  • \S 匹配非空格
  • \b 匹配边界
  • \B 匹配非边界
  • \n 换行符
  • \0 查找 NUL字符
  • \f 查找换页符
  • \r 查找回车符
  • \t 查找制表符
  • \v 查找垂直制表符
  • . 除换行符以外的任意字符
  • ? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。

运算符

  • | 替换,"或"操作
  • / 转义

字符串方法可以配合正则使用

  • replace
  • match 类似于exec (查找返回对应的值[值是数组] 没有找到返回null) **支持全局

模式

  • 贪婪模式 (/\d{3,6}/g) 取最大值
  • 非贪婪模式(懒得模式) (/\d{3,6}?/g) 取最小值

常用的正则

  • 手机号码正则
javascript
var phone = /^1[345678]\d{9}$/g;
var phone = /^1\d{10}$/;
  • Email 正则
javascript
var email = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;

第三章 面试题框架篇

3.1 Vue 面试题

面试题:那你能讲⼀讲MVVM

INFO

MVVM是 Model-View-ViewModel 缩写,也就是把 MVC 中的 Controller 演变成 ViewModel 。 Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到viewModel层并⾃动将数据渲染到⻚⾯中,视图变化的时候会通知viewModel层更新数据

面试题:MVVM 的实现原理

INFO

  • 响应式:vue如何监听data的属性变化
  • 模板解析:vue的模板是如何被解析的
  • 渲染:vue模板是如何被渲染成HTML的

面试题:什么是生命周期

INFO

vue中每个组件都是独立的,每个组件都有一个属于它的生命周期, 从一个组件创建、数据初始化、挂载、更新、销毁,这就是一个组件所谓的生命周期。

面试题:Vue2.x 生命周期

  • 有哪些生命周期

INFO

  • 系统自带:
    • beforeCreate 组件创建之前
    • created 组件创建之后
    • beforeMount 组价挂载到页面之前执行
    • mounted 组件挂载到页面之后执行
    • beforeUpdate 组件更新之前
    • updated 组件更新之后
    • beforeDestroy 组件销毁之前
    • destroyed 组件销毁后
    • errorCaptured
  • 一旦进入到页面或者组件,会执行哪些生命周期,顺序

INFO

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • 在哪个阶段有eldata

INFO

  • beforeCreate 啥也没有
  • created 有data没有el
  • beforeMount 有data没有el
  • mounted 都有
  • 如果加入了keep-alive会多俩个生命周期

INFO

  • activated
  • deactivated
  • 如果加入了keep-alive,第一次进入组件会执行哪些生命?

INFO

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • activated
  • 如果加入了keep-alive,第二次或者第N次进入组件会执行哪些生命周期?

INFO

  • 只执行一个生命周期:activated

面试题:vue3 生命周期

INFO

  • setup 开始创建组件
  • onBeforeMount 组价挂载到页面之前执行
  • onMounted 组件挂载到页面之后执行
  • onBeforeUpdate 组件更新之前
  • onUpdated 组件更新之后
  • onBeforeUnmount 组件销毁之前
  • onUnmounted 组件销毁后
  • onErrorCaptured

面试题:生命周期对比

INFO

  • Vue2--------------vue3
  • beforeCreate -> setup()
  • created -> setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • activated -> onActivated
  • deactivated -> onDeactivated
  • errorCaptured -> onErrorCaptured

面试题:Vue 的⽗组件和⼦组件⽣命周期钩⼦执⾏顺序是什么?

  • 渲染过程:

INFO

  • ⽗组件挂载完成⼀定是等⼦组件都挂载完成后,才算是⽗组件挂载完,所以⽗组件的mounted在⼦组件mouted之后

  • ⽗beforeCreate -> ⽗created -> ⽗beforeMount -> ⼦beforeCreate -> ⼦created -> ⼦beforeMount-> ⼦mounted -> ⽗mounted

  • ⼦组件更新过程:

INFO

  • 影响到⽗组件: ⽗beforeUpdate -> ⼦beforeUpdate->⼦updated -> ⽗updted
  • 不影响⽗组件: ⼦beforeUpdate -> ⼦updated
  • ⽗组件更新过程:

INFO

  • 影响到⼦组件: ⽗beforeUpdate -> ⼦beforeUpdate->⼦updated -> ⽗updted
  • 不影响⼦组件: ⽗beforeUpdate -> ⽗updated
  • 销毁过程:

INFO

  • ⽗beforeDestroy -> ⼦beforeDestroy -> ⼦destroyed -> ⽗destroyed

INFO

看起来很多好像很难记忆,其实只要理解了,不管是哪种情况,都⼀定是⽗组件等待⼦组件完成后,才 会执⾏⾃⼰对应完成的钩⼦,就可以很容易记住

面试题:DOM 渲染在那个生命周期阶段内完成

  • DOM 渲染在 mounted 周期中就已经完成

面试题:发送请求在created还是mounted?

INFO

这个问题具体要看项目和业务的情况了,因为组件的加载顺序是,父组件引入了子组件,那么先执行父的前3个生命周期,再执行子的前4个生命周期,那么如果我们的业务是父组件引入子组件,并且优先加载子组件的数据,那么在父组件中当前的请求要房mounted中,如果当前组件没有依赖关系那么放在哪个生命周期中请求都是可以的。

面试题:为什么发送请求不在beforeCreate里?beforeCreate和created有什么区别?

  • 为什么发送请求不在beforeCreate里?
  • 因为:如果请求是在methods封装好了,在beforeCreate调用的时候,beforeCreate阶段是拿不到methods里面的方法的(会报错了)。
  • beforeCreate和created有什么区别?

INFO

  • beforeCreate没有$data

  • created中有$data

  • created是可以拿到methods的方法的

  • beforeCreate拿不到methods的方法

面试题:你在什么情况下用过哪些生命周期?说一说生命周期使用场景

INFO

  • created   ===> 单组件请求
  • mounted   ===> 同步可以获取dom,如果先子组件请求后父组件请求
  • activated ===> 判断id是否相等,如果不相同发起请求
  • destroyed ===> 关闭页面记录视频播放的时间,初始化的时候从上一次的历史开始播放

面试题:vue 最大特点是什么或者说 vue 核心是什么

  • vue 最大特点我感觉就是“组件化“和”数据驱动“
  • 组件化就是可以将页面和页面中可复用的元素都看做成组件,写页面的过程,就是写组件,然后页面是由这些组件“拼接“起来的组件树
  • 数据驱动就是让我们只关注数据层,只要数据变化,页面(即视图层)会自动更新,至于如何操作dom,完全交由vue去完成,咱们只关注数据,数据变了,页面自动同步变化了,很方便

面试题:vue 常用基本指令有哪些

INFO

  • v-if:根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建
  • v-show:根据表达式之真假值,切换元素的 display CSS 属性。
  • v-for:循环指令,基于一个数组或者对象渲染一个列表,vue 2.0以上必须需配合 key值 使用。
  • v-bind:动态地绑定一个或多个特性,或一个组件 prop 到表达式。
  • v-on:用于监听指定元素的DOM事件,比如点击事件。绑定事件监听器。
  • v-model:实现表单输入和应用状态之间的双向绑定
  • v-pre:跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
  • v-once:只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

面试题:谈谈你对 keep-alive 的了解

  • 是什么
    • vue系统自带的一个组件,功能:是来缓存组件的。===》提升性能
  • 使用场景
    • 就是来缓存组件,提升项目的性能。具体实现比如:首页进入到详情页,如果用户在首页每次点击都是相同的,那么详情页就没必要请求N次了,直接缓存起来就可以了,当然如果点击的不是同一个,那么就直接请求
  • 一旦使用keep-live会多出两个生命周期
    • activated
    • deactivated
  • 优势
    • 在组件切换过程中,将状态保留在内存中,防止重复渲染DOM,减少了加载时间,提升了用户体验

面试题:v-if 和 v-show 区别

  • 展示形式不同
    • v-if是 创建一个dom节点
    • v-show 是display:none 、 block
  • 使用场景不同
    • 初次加载v-if要比v-show好,页面不会做加载盒子
    • 频繁切换v-show要比v-if好,创建和删除的开销太大了,显示和隐藏开销较小

INFO

总结:v-if 会在切换过程中对条件块的事件监听器和⼦组件进⾏销毁和重建,如果初始条件是false,则什么 都不做,直到条件第⼀次为true时才开始渲染模块。 v-show 只是基于css进⾏切换,不管初始条件是什么,都会渲染。 所以, v-if 切换的开销更⼤,⽽ v-show 初始化渲染开销更⼤,在需要频繁切换,或者切换的部分 dom很复杂时,使⽤ v-show 更合适。 渲染后很少切换的则使⽤ v-if 更合适

面试题:v-if 和 v-for 优先级

  • v-for的优先级要比v-if高
  • 证明这件事在vue源码11002行左右:
javascript
  if (el.staticRoot && !el.staticProcessed) {
        return genStatic(el, state)
      } else if (el.once && !el.onceProcessed) {
        return genOnce(el, state)
      } else if (el.for && !el.forProcessed) {
        return genFor(el, state)
      } else if (el.if && !el.ifProcessed) {
        return genIf(el, state)
      } else if (el.tag === 'template' && !el.slotTarget && !state.pre) {
        return genChildren(el, state) || 'void 0'
      } else if (el.tag === 'slot') {
        return genSlot(el, state)
  • 注:v-if和v-for不要写在同一个节点上,要不性能很差(v-if写在父节点上)

INFO

首先不要把 v-if 与 v-for 用在同一个元素上,原因:v-for 比 v-if 优先, 如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染 很小一部分的时候

面试题:为什么 v-for 和 v-if 不建议⽤在⼀起

INFO

当 v-for 和 v-if 处于同⼀个节点时, v-for 的优先级⽐ v-if 更⾼,这意味着 v-if 将分别重复 运⾏于每个 v-for 循环中。如果要遍历的数组很⼤,⽽真正要展示的数据很少时,这将造成很⼤的性能浪费。 这种场景建议使⽤ computed ,先对数据进⾏过滤

面试题:v-for 中 key 的作⽤是什么

INFO

key 是给每个 vnode 指定的唯⼀ id ,在同级的 vnode diff 过程中,可以根据 key 快速的对⽐, 来判断是否为相同节点,并且利⽤ key 的唯⼀性可以⽣成 map 来更快的获取相应的节点。 另外指定 key 后,就不再采⽤“就地复⽤”策略了,可以保证渲染的准确性

它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

面试题:v-for 中 key 为什么不用 index 作为 key 呢

INFO

当以数组的下标index作为key值时,其中一个元素(如增删改查)发生了变化就有可能导致所有元素的key值发生变化

为什么不用index作为key呢,是因为,如果在一个v-for list里面,删除中间的一个item,这个时候这个item后面所有的index都会变化,那么diff就会计算出后面的item的key-index映射都发生了变化,就会全部重新渲染,大大影响了性能。而且这也会导致一些bug,比如当删除了item2的时候,再选中item3就会变成选中item4

面试题:ref 是什么?

  • 是什么?
    • 用来获取dom
  • 场景?
    • 如果项目中使用插件,并且插件是要获取dom的,就可以使用ref
  • 作用
    • ref 被用来给 DOM 元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。 如果在普 通的 DOM 元素上使用,引用信息就是元素; 如果用在子组件上,引用信息就是组件实例 注意:只要想要在 Vue 中直接操作 DOM 元素,就必须用 ref 属性进行注册

面试题:nextTick 是什么?

  • 是什么?
    • 当dom更新完毕执行内部代码
  • 场景?
    • 使用插件时候会用到,例如:new Swiper这个插件可能会获取到当前元素的宽度或者高度,等dom加载完毕再去获取宽度或者高度就不会有问题了

面试题:vue 插槽的理解和使用及作用域插槽

  • 什么是插槽?
  • 插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。
  • 插槽的使用 - 默认插槽
  • 描述:
  • 默认插槽就是指没有名字的插槽,子组件未定义的名字的插槽,父级将会把 未指定插槽的填充的内容填充到默认插槽中。
  • 插槽的使用 - 具名插槽
  • 描述:
  • 具名插槽其实就是给插槽娶个名字。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中。
  • 作用域插槽
  • 描述:
  • 作用域插槽其实就是带数据的插槽,即带参数的插槽,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容。

面试题:scoped 原理

  • 作用:让样式在本组件中生效,不影响其他组件。
  • 原理:给节点新增自定义属性,然后css根据属性选择器添加样式。

INFO

  • 在Vue文件中的style标签上有一个特殊的属性,scoped
  • 当一个style标签拥有scoped属性时候,它的css样式只能用于当前的Vue组件,可以使组件的样式不相互污染。
  • 如果一个项目的所有style标签都加上了scoped属性,相当于实现了样式的模块化

面试题:Vue 中如何做样式穿透

  • stylus样式穿透使用:>>>
  • sass和less使用:/deep/
  • 通用使用: :v-deep

VUE 组件重新渲染(组件重载)的 3 种方式

  • 使用 v-if v-if可以实现 true (加载)和false(卸载)
  • 使用组件中的 :key (推荐) <aComp :key="keys"></aComp>
  • 使用 $forceUpdate()

面试题:Vue 组件传值

INFO

  • props/$emit:可以实现父子组件的双向通信,在日常的父子组件通信中一般会作为我们的最常用选择。
  • v-slot:可以实现父子组件单向通信(父向子传值),在实现可复用组件,向组件中传入DOM节点、html等内容以及某些组件库的表格值二次处理等情况时,可以优先考虑v-slot
  • $refs/$parent/$children/$root:可以实现父子组件双向通信,其中 $root可以实现根组件实例向子孙组件跨级单向传值。在父组件没有传递值或通过v-on绑定监听时,父子间想要获取彼此的属性或方法可以考虑使用这些api。
  • $attrs/$listeners:能够实现跨级双向通信,能够让你简单的获取传入的属性和绑定的监听,并且方便地向下级子组件传递,在构建高级组件时十分好用。
  • provide/inject:可以实现跨级单向通信,轻量地向子孙组件注入依赖,这是你在实现高级组件、创建组件库时的不二之选。
  • eventBus:可以实现全局通信,在项目规模不大的情况下,可以利用eventBus实现全局的事件监听。但是eventBus要慎用,避免全局污染和内存泄漏等情况。
  • Vuex:可以实现全局通信,是vue项目全局状态管理的最佳实践。在项目比较庞大,想要集中式管理全局组件状态时,那么安装Vuex准没错
父组件如何直接修改子组件的值
vue
<List ref="child"></List>
this.$refs.child.xxx = 'yyyy';
子组件如何直接修改父组件的值
  • 子组件中可以使用:this.$parent.xxx去修改
如何找到父组件
  • this.$parent 找到当前组件的父组件,如果找不到返回自身
如何找到根组件
  • this.$root
获取到当前组件的所有子组件的
  • this.$children
面试题:$el$data干嘛的
  • $el 获取当前组件的根节点
  • $data 获取当前组件data数据的

面试题:vue 中组件 data 为什么是 return ⼀个对象的函数,⽽不是直接是个对象

  • 因为一个组件是可以共享的,但他们的data是私有的,所以每个组件都要return一个新的data对象,返回一个唯一的对象,不要和其他组件共用一个对象

INFO

当data定义为对象后,这就表示所有的组件实例共⽤了⼀份data数据,因此,⽆论在哪个组件实例中修改了data,都会影响到所有的组件实例。组件中的data写成⼀个函数,数据以函数返回值形式定义,这样每复⽤⼀次组件,就会返回⼀份新的data,类似于给每个组件实例创建⼀个私有的数据空间,让各个组件实例维护各⾃的数据。⽽单纯的写成对象形式,就使得所有组件实例共⽤了⼀份data,就会造成⼀个变了全都会变的结果

面试题:watch 有哪些属性,分别有什么用?

javascript
watch: {
    obj: {
       handler () { // 执行回调
           // do something
       },
       deep: true, // 是否进行深度监听
       immediate: true // 是否初始执行handler函数
    }
}

面试题:computed、methods、watch 有什么区别?

  • computed:计算属性

    • 可以监听某些数据的变化,并且有缓存。
    • 如果一进入页面调用,就会触发
  • methods : 可以放入函数

    • 没有缓存
    • 如果一进入页面调用,就会触发
  • watch :监听(路由和数据)

    • 当数据发生改变时,才会触发
    • 可以得到现在的值和过去的值
  • computed vs methods区别

    • computed是有缓存的
    • methods没有缓存
  • computed vs watch区别

    • watch是监听,数据或者路由发生了改变才可以响应(执行)
    • computed计算某一个属性的改变,如果某一个值改变了,计算属性会监听到进行返回
    • watch是当前监听到数据改变了,才会执行内部代码

INFO

  • methods中都是封装好的函数,无论是否有变化只要触发就会执行
  • computed:是vue独有的特性计算属性,可以对data中的依赖项再重新计算,得到一个新值,应用到视图中
  • 和methods本质区别是computed是可缓存的,也就是说computed中的依赖项没有变化,则computed中的值就不会重新计算,而methods中的函数是没有缓存的。
  • Watch是监听data和计算属性中的新旧变化。

面试题:vue 指令

  • 自定义指令也像组件那样存在钩子函数:
  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用
  • unbind:只调用一次,指令与元素解绑时调用
  • 所有的钩子函数的参数都有以下:
    • el:指令所绑定的元素,可以用来直接操作 DOM
    • binding:一个对象,包含以下 property
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
    • oldValue:指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用。
    • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
    • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
    • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
    • vnode:Vue 编译生成的虚拟节点
    • oldVnode:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用

面试题:在vue中说说你知道的自定义指令

  • 自定义指令两种:

    • 一种全局自定义指令,vue.js对象提供了directive方法,可以用来自定义指令,directive方法接收两个参数
    • 一个是指令名称,
    • 另一个是函数;
  • 第二种是局部自定义指令,通过组件的directives属性定义。

面试题:Vue2.0 中如何检测数组变化?

INFO

Vue 的 Observer 对数组做了单独的处理,对数组的⽅法进⾏编译,并赋值给数组属性的 __proto__

属性上,因为原型链的机制,找到对应的⽅法就不会继续往上找了。编译⽅法中会对⼀些会增加索引的

⽅法( pushunshiftsplice )进⾏⼿动 observe。

具体重写的有

  • pushpopshiftunshiftsortreversesplice (这七个都是会改变原数组的)

面试题:props 和 data 优先级谁高?

  • props ===> methods ===> data ===> computed ===>watch

面试题:Vuex 有哪些属性?

  • state、getters、mutations、actions、modules
  • state 类似于组件中data,存放数据
  • getters 类型于组件中computed
  • mutations 类似于组件中methods
  • actions 提交mutations
  • modules 把以上4个属性再细分,让仓库更好管理
  • 什么场景用Vuex:共享、方便管理、方便维护、组件传值......
    • 项目:购物车数据,订单数据,用户的登录信息....

面试题:vuex 的理解

INFO

vuex是一个状态管理工具,主要解决大中型复杂项目的数据共享问题,主要包括state,actions,mutations,gettersmodules 5个要素,主要流程:组件通过dispatchactionsactions是异步操作,再actions中通过commitmutationsmutations再通过逻辑操作改变state,从而同步到组件,更新其数据状态,而getters相当于组件的计算属性对,组件中获取到的数据做提前处理的.再说到辅助函数的作用

面试题:Vuex 是单向数据流还是双向数据流?

  • Vuex是单向数据流

面试题:说一下你对单向数据流的理解

INFO

单向数据流主要是vue 组件间传递数据是单向的,即数据总是由父组件传递给子组件,子组件在其内部维护自己的数据,但它无权修改父组件传递给它的数据,当开发者尝试这样做的时候,vue 将会报错。这样做是为了组件间更好的维护。 在开发中可能有多个子组件依赖于父组件的某个数据,假如子组件可以修改父组件数据的话,一个子组件变化会引发所有依赖这个数据的子组件发生变化,所以 vue 不推荐子组件修改父组件的数据

面试题:Vuex 中的 mutaitonsactions 区别

  • mutaitons : 都是同步事物

  • actions : 可以包含任意异步操作

  • ***在调试中就看出来

面试题:Vuex 如何做持久化存储

  • Vuex本身不是持久化存储
    1. 使用localStorage自己写
    1. 使用vuex-persist插件

面试题:Vue 设置代理

  • vue.config.js
javascript
module.exports = {
  publicPath: "./",
  devServer: {
    proxy: "http://localhost:3000",
  },
};

面试题:Vue 项目打包上线

  • 自测==>修改路由模式
  • 代理不生效,使用ENV
  • 修改路径

面试题:Vue 路由模式

面试题:vue-router hash 模式和 history 模式有什么区别?

  • url 展示上,hash 模式有“#”,history 模式没有
    • const code = generate(ast, options)
  • 刷新⻚⾯时,hash 模式可以正常加载到 hash 值对应的⻚⾯,⽽ history 没有处理的话,会返回
    • 404,⼀般需要后端将所有⻚⾯都配置重定向到⾸⻚路由。
  • 兼容性。hash 可以⽀持低版本浏览器和 IE。

面试题:vue-router hash 模式和 history 模式是如何实现的?

  • hash 模式:

    • # 后⾯ hash 值的变化,不会导致浏览器向服务器发出请求,浏览器不发出请求,就不会刷新⻚⾯。同时通过监听 hashchange 事件可以知道 hash 发⽣了哪些变化,然后根据 hash 变化来实现更新⻚⾯部分内容的操作。
  • history 模式:

    • history 模式的实现,主要是 HTML5 标准发布的两个 API, pushState 和 replaceState ,这两个 API 可以在改变 url,但是不会发送请求。这样就可以监听 url 变化来实现更新⻚⾯部分内容的操作

面试题:SPA 单页面应用和传统页面跳转有什么区别?

  • SPA跳转是一个页面进行切换

  • 传统页面跳转就是跳转不同的html了

  • SPA对于seo部分不是特别好,只能收录一个

  • 传统的页面对于seo比较好,多个html文件收录

面试题:介绍一下 SPA 以及 SPA 有什么缺点

  • SPA是什么?单页面应用
  • 缺点:
    • SEO优化不好
    • 性能不是特别好

面试题:Vue 路径传值

  • 显式 http://localhost:8080/about?a=1

    • 传:`this.$router.push({
    	path:'/about',
    	query:{
    		a:1
    	}
    })`
    
    • 接:this.$route.query.a
  • 隐式 http://localhost:8080/about

    • 传:this.$router.push({ name:'About', params:{ a:1 } })
    • 接:this.$route.params.a

面试题:路由导航守卫有哪些

  • 全局、路由独享、组件内

  • 全局

    • beforeEach、beforeResolve、afterEach
  • 路由独享

    • beforeEnter
  • 组件内

    • beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
  • 使用场景:判断是否登录,如果登录就next否则就跳转到登录页面

  • 场景:要去拦截,判断用户是否是登录状态。功能:进入地址管理,用户如果没有登录是进入不了地址管理(在进入之前判断拦截),需要先登录

面试题:Vue 动态路由

  • 场景:详情页(文章、商品)
  • router.js配置:
javascript
	{
    path: "/list",
    name: "List",
    children:[
      {
        path:"/list/:id",
        name:'Details',
        component: () =>
          import("../views/Details.vue"),
      }
    ],
    component: () =>
      import("../views/List.vue"),
  },

  接:this.$route.params.id

面试题:vue2 双向绑定原理

INFO

  • vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。
  • 通过Object.defineProperty()来实现数据劫持的。
  • 实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。
  • 实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。
  • 实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。

INFO

  • Vue 的响应式是通过 Object.defineProperty 对数据进⾏劫持,并结合观察者模式实现。 Vue 利⽤Object.defineProperty 创建⼀个 observe 来劫持监听所有的属性,把这些属性全部转为 getter和 setter 。

  • Vue 中每个组件实例都会对应⼀个 watcher 实例,它会在组件渲染的过程中把使⽤过的数据属性通过 getter 收集为依赖。之后当依赖项的setter 触发时,会通知 watcher ,从⽽使它关联的组件重新渲染。

vue3面试题

面试题:vue3 双向绑定原理

  • Vue3.x改⽤ Proxy 替代Object.defineProperty。因为Proxy可以直接监听对象和数组的变化,并且有多达13种拦截⽅法。并且作为新标准将受到浏览器⼚商重点持续的性能优化。

Proxy 只会代理对象的第⼀层,那么 Vue3 ⼜是怎样处理这个问题的呢?

  • 判断当前Reflect.get的返回值是否为Object,如果是则再通过 reactive ⽅法做代理, 这样就实现了深度观测。

监测数组的时候可能触发多次 get/set,那么如何防⽌触发多次呢?

  • 我们可以判断key是否为当前被代理对象target⾃身属性,也可以判断旧值与新值是否相等,只有满⾜以上两个条件之⼀时,才有可能执⾏trigger

面试题:vue3.0 相对于 vue2.x 有哪些变化?

INFO

  • 监测机制的改变(Object.defineProperty(后添加的值劫持不到) —> new Proxy
  • $set在vue3没有 new Proxy解决了
  • 关于写法 vue2是选项式api vue3可以向下兼容(选项式api) 也可以是组合式api和steup语法糖形式
  • v-if和v-for优先级不同 $ref $children 不同
  • 模板
  • 对象式的组件声明⽅式 (class)
  • 使⽤ts
  • 其它⽅⾯的更改:⽀持⾃定义渲染器、 ⽀持 Fragment(多个根节点)和 Protal(在 dom 其他部
  • 分渲染组建内容)组件、基于 treeshaking 优化,提供了更多的内置功能

INFO

首先vue2和vue3双向绑定方法不同,vue2是Object.defineProperty,vue3是new Proxy,简单来说他两的区别是Object.defineProperty后添加的属性劫持不到,所以vue2为了解决数据更新视图不更新问题,增加了一个api $set 但是vue3中没有这个问题 所以没有$set 即使后添加的属性也能劫持到 还不需要循环 关于写法上vue2是选项式api vue3可以向下兼容(选项式api) 也可以是组合式api和steup语法糖形式 其他的就是细节问题 比如说v-if和v-for优先级不同,⽀持多个根节点,$ref 和 $children 不同

面试题:vue3如果用setup写如何获取类似于vue2中的this?

javascript
import { getCurrentInstance } from vue
let app = getCurrentInstance();
console.log( app.appContext.app.config.globalProperties.$loading )

面试题:vue3常用api有哪些

INFO

  • createApp() ==》 创建一个应用实例。

    • 说明:等于vue2的==》new Vue()
    • 使用场景:写插件(封装全局组件会使用)
  • provde/inject ==》依赖注入

    • 说明:其实就是传值使用场景:某一个父组件传值 到后代组件,如果层级过多传递麻烦,所以使用
    • 缺点:不好维护和查询数据来源
  • directive

    • 说明: 自定义指令
    • 场景:后台管理系统中的按钮权限控制 ( 一个用户拥有某些权限,但是只能查看和修改,不能删除)
  • mixin 说明: 1.全局混入 2。 局部

    • 场景:可以添加生命周期,我在小程序的分享功能会用到
    • 缺点:不好维护和查询数据来源
  • app.config.globalProperties

    • 说明:获取vue这个全局对象的属性和方法
    • 场景:自己封装插件的时候需要把方法添加到对象中
  • nextTick

    • 说明: 等待下一次 DOM 更新刷新的工具方法: nextTick返回一个pormise.回调函数是放在promise中的,所以是异步执行的
    • 场景:就是把dom要更新,那么vue是数据驱动dom,所以数据的赋值就要在nextTick进行
  • computed

    • 说明:计算属性
    • 场景:有缓存
  • reactive、ref

    • 说明:来定义数据的和vue2的data类似
  • watch

    • 说明:监听 (vue3不需要深度监听)
  • markRaw()

    • 说明: 不被new Proxy代理,说白了就是静态的数据
  • defineProps()

    • 说明: 父组件传递的值,子组件使用setup的形式,需要用defineProps接收
  • defineEmits()

    • 当前组件使用setup形式,自定义事件需要使用defineEmits
  • slot

    • 说明:分为 1.匿名 2.具名 3.作用域
    • 场景: 后台管理系统,左侧是固定菜单,右侧是不固定内容,那么右侧就是slot

面试题:请介绍一下vue3常用的响应式数据类型

  • ref:基本类型
  • reactive:复杂类型
  • toRef:解构某一个值
  • toRefs:解构多个值

面试题:请介绍一下vue3常用的响应式数据类型

  • teleport组件是一个传送门
    • 假如自己写弹出框,需要在页面居中位置展示,不受当前组件的限制,可以把盒子传送到body中

Nuxt2面试题

面试题:nuxt.config.js 有哪些常用配置

  • build:应用依赖第三方模块
  • cache:该配置项让你开启组件缓存策略以提升渲染性能。
  • css:该配置项用于定义应用的全局(所有页面均需引用的)样式文件、模块或第三方库。
  • dev:该配置项用于配置 Nuxt.js 应用是开发还是生产模式。
  • env:该配置项用于定义应用客户端和服务端的环境变量。
  • generate:该配置项用于定义每个动态路由的参数,Nuxt.js 依据这些路由配置生成对应目录结构的静态文件。
  • head:该配置项用于配置应用默认的meta标签。
  • loading:该配置项用于个性化定制 Nuxt.js 使用的加载组件。
  • modules:该配置项允许您将Nuxt模块添加到项目中。
  • modulesDir:该配置项允许您定义Nuxt.js应用程序的node_modules文件夹
  • plugins:该配置项用于配置那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。
  • rootDir:该配置项用于配置 Nuxt.js 应用的根目录。
  • outer:该配置项可用于覆盖 Nuxt.js 默认的 vue-router 配置。
  • srcDir:该配置项用于配置应用的源码目录路径。
  • transition:该配置项用于个性化配置应用过渡效果属性的默认值。

虚拟DOM

面试题:什么是虚拟 DOM

  • 其实就是数据,把dom变成数据结构。

面试题:虚拟 dom 比真实 dom 有什么优势

  • vue的虚拟DOM有什么好处?

  • ⾸先了解浏览器显⽰⽹页经历的5个过程

    • 解析标签,⽣成元素树(DOM树)
    • 解析样式,⽣成样式树
    • ⽣成元素与样式的关系
    • ⽣成元素的显⽰坐标
    • 显⽰页⾯
  • 修改真实DOM

    • 每修改⼀个元素,那么这5个过程都要重新⾛⼀次。修改10个元素就⾛10遍。
  • 修改虚拟DOM

    • 虚拟DOM存储在内存中,对10个元素的修改是在虚拟DOM中进⾏,修改完后,⽐较虚拟DOM和真实DOM的差异,当有差异时,再⼀次过
    • 去更新⽹页的显⽰,⽽不是⾛10遍过程。
  • 虚拟 DOM 好处

    • 速度快,减⼩了页⾯渲染过程的次数
    • 虚拟DOM具有批处理和高效的Diff算法,最终表现在DOM上的修改只是变更的部分,可以保证非常高效的渲染,优化性能.
  • 缺点:

    • 首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。

面试题:diff 算法

  • 利用diff算法可以更多提升dom之间对比的性能(采用虚拟dom数据进行对比)。
sh
# 搭建环境
npm init -y

cnpm install webpack@5 webpack-cli@3 webpack-dev-server@3 -S

cnpm install snabbdom -S

# 新建webpack.config.js
#
# 配置webpack.config.js

面试题:讲一下 MVVM

  • M就是data的model层
  • V就是view视图层
  • VM就是理解为v-model原理实现,通过view更新model

3.2 微信小程序面试题

面试题:简述微信小程序原理

  • 微信小程序采用 JavaScript、WXML、WXSS 三种技术进行开发,本质就是一个单页面应用,所有的页面渲染和事件处理,都在一个页面内进行,但又可以通过微信客户端调用原生的各种接口

  • 微信的架构,是数据驱动的架构模式,它的 UI 和数据是分离的,所有的页面更新,都需要通过对数据的更改来实现

  • 小程序分为两个部分 webview 和 appService 。其中 webview 主要用来展现 UI ,appService 有来处理业务逻辑、数据及接口调用。它们在两个进程中运行,通过系统层 JSBridge 实现通信,实现 UI 的渲染、事件的处理

面试题:小程序的双向绑定和 vue 哪里不一样

  • 小程序直接 this.data 的属性是不可以同步到视图的,必须调用:
javascript
this.setData({
  // 这里设置
});

面试题:小程序的 wxss 和 css 有哪些不一样的地方

  • WXSS 和 CSS 类似,不过在 CSS 的基础上做了一些补充和修改

尺寸单位 rpx

  • rpx 是响应式像素,可以根据屏幕宽度进行自适应。规定屏幕宽为 750rpx。如在 iPhone6 上,屏幕宽度为 375px,共有 750 个物理像素,则 750rpx = 375px = 750 物理像素

使用 @import 标识符来导入外联样式。@import 后跟需要导入的外联样式表的相对路径,用;表示语句结束

css
/** index.wxss **/
@import "./base.wxss";

.container {
  color: red;
}

面试题:小程序 rpx 单位转换

INFO

  • 尺寸单位

  • rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

  • 设备 rpx换算px (屏幕宽度/750) px换算rpx (750/屏幕宽度)

  • iPhone5 1rpx = 0.42px 1px = 2.34rpx

  • iPhone6 1rpx = 0.5px 1px = 2rpx

  • iPhone6 Plus 1rpx = 0.552px 1px = 1.81rpx

  • 建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。

  • 注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况

面试题:小程序的生命周期函数

INFO

  • onLoad() 页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数
  • onShow() 页面显示/切入前台时触发
  • onReady() 页面初次渲染完成时触发。一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互
  • onHide() 页面隐藏/切入后台时触发。 如 navigateTo 或底部 tab 切换到其他页面,小程序切入后台等
  • onUnload() 页面卸载时触发。如 redirectTo 或 navigateBack 到其他页面时
  • onPullDownRefresh() 触发下拉刷新时执行
  • onReachBottom() 页面触底时执行
  • onShareAppMessage() 页面被用户分享时执行
  • onPageScroll() 页面滚动时执行
  • onResize() 页面尺寸变化时执行

面试题:简述下 wx.navigateTo(), wx.redirectTo(), wx.switchTab(), wx.navigateBack(), wx.reLaunch()的区别

INFO

  • wx.navigateTo():保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面
  • wx.redirectTo():关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面
  • wx.switchTab():跳转到 abBar 页面,并关闭其他所有非 tabBar 页面
  • wx.navigateBack():关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层
  • wx.reLaunch():关闭所有页面,打开到应用内的某个页面

面试题:小程序页面间有哪些传递数据的方法

使用全局变量实现数据传递 在 app.js 文件中定义全局变量 globalData, 将需要存储的信息存放在里面

javascript
// app.js

App({
  // 全局变量
  globalData: {
    userInfo: null,
  },
});

使用的时候,直接使用 getApp() 拿到存储的信息

使用 wx.navigateTowx.redirectTo 的时候,可以将部分数据放在 url 里面,并在新页面 onLoad 的时候初始化

javascript
//pageA.js

// Navigate
wx.navigateTo({
  url: '../pageD/pageD?name=raymond&gender=male',
})

// Redirect
wx.redirectTo({
  url: '../pageD/pageD?name=raymond&gender=male',
})


// pageB.js
...
  onLoad: function(option){
    console.log(option.name + 'is' + option.gender)
    this.setData({
      option: option
    })
  }
  • 需要注意的问题:
  • wx.navigateTowx.redirectTo 不允许跳转到 tab 所包含的页面
  • onLoad 只执行一次

使用本地缓存 Storage 相关

javascript
wx.setStorageSync("name", "xxxx");

wx.getStorageSync(name);

父组件向子组件传值( properties )

javascript
<w-child fatherName='winne' fatherAge='22'></w-child>

// 子组件在js中获取父组件中传过来的值
// child.js
properties: {  // 在这里拿到了数据之后可以直接使用了(在wxml模板渲染,或者js中使用this.data.fatherName/this.properties.fatherName 都能获取到),不要直接修改properties属性中的数据
  fatherName: {
    type: String
  },
  fatherAge: Number
}

子组件向父组件传值( this.triggerEvent() )

javascript
// 子组件触发自定义事件,传递数据给父组件
<!-- child.wxml  -->
<view class="navi-item" data-index="0" bindtap="onChangeAnchor">tab</view>

// 子组件在点击事件中主动触发自定义事件
// child.js
onChangeAnchor(e) {
      var index = e.target.dataset.index
      //子组件传值给父组件
      let myEventDetail = { // 需要传递什么数据就在这个对象中写
        val: index
      }
      // myEventDetail 对象,提供给事件监听函数的参数数据
      // changeNaviIndex 是自定义名称事件,父组件中监听使用
      this.triggerEvent('changeNaviIndex', myEventDetail)
    }
javascript
// 父组件wxml中监听子组件的自定义事件
// <!-- parents.wxml-->
// <!-- 注意这里写的事件监听名字-->
 <w-child bind:changeNaviIndex="onGetIndex" />

// 父组件的js中书写事件函数,获取子组件传递过来的数据
// parents.js
  onGetIndex( paramData) { // paramData参数就是子组件的this.triggerEvent()
    console.log(paramData.detail.val)  // 0
  }

面试题:如何自定义头部?

javascript
// app.json进行配置

"window":{
    "navigationStyle":"custom",
}

面试题:哪些方法可以用来提高微信小程序的应用速度

  • 提高页面加载速度

  • 用户行为预测

  • 减少默认 data 的大小

  • 组件化方案

面试题:微信小程序的优劣势

优势

  • 即用即走,不用安装,省流量,省安装时间,不占用桌面
  • 依托微信流量,天生推广传播优势
  • 开发成本比 App 低

缺点

  • 用户留存,即用即走是优势,也存在一些问题
  • 入口相对传统 App 要深很多
  • 限制较多,页面大小不能超过1M。不能打开超过5个层级的页面

面试题:怎么解决小程序的异步请求问题

  • 小程序支持 ES6 语法
    • 在返回成功的回调里面处理逻辑
    • Promise 异步
    • async/await

面试题:如何实现下拉刷新

  • 首先在全局 config 中的 window 配置 enablePullDownRefresh
  • 在 Page 中定义 onPullDownRefresh 钩子函数,到达下拉刷新条件后,该钩子函数执行,发起请求方法
  • 请求返回后,调用 wx.stopPullDownRefresh 停止下拉刷新

面试题:bindtap 和 catchtap 的区别是什么

  • 相同点:首先他们都是作为点击事件函数,就是点击时触发。在这个作用上他们是一样的,可以不做区分

  • 不同点:他们的不同点主要是bindtap是不会阻止冒泡事件的,catchtap是阻值冒泡的

面试题:小程序关联微信公众号如何确定用户的唯一性

  • 如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过 unionid 来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的 unionid 是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid 是相同的

面试题:不校验 URL

  • 工具==》详情==》本地设置==》不校验合法域名 : 项目上线前URL一定要请求到(不勾选也可以请求到数据)

3.3 uni-app 面试题

面试题:生命周期

  • 应用生命周期、页面生命周期、组件生命周期

面试题:条件编译

  • 在工具中,打if出现的条件编译
html
<!-- #ifdef H5 -->
<h1>这是h5端</h1>
<!-- #endif -->

第四章 面试题性能优化篇

4.1 加载优化

  • http请求
    • 能不能减少(能不能合并)
  • 图片的雪碧图
  • script标签位置
  • link标签(css引入)

4.2 图片优化

  • 图片懒加载
  • 响应式图片
  • webp代替其他格式
  • 小图标可以改用字体图标

4.3 渲染优化

  • 减少重绘和回流
  • 改变位置使用transform
  • 动画尽量用requestAnimationFrame,不要用定时器

4.4 首屏优化

  • 长列表
  • 项目的html文件、css文件、图片、js文件压缩打包

4.5 vue 优化

  • keep-alive 缓存组件
  • 路由懒加载
  • 内容使用
    • v-if和v-show
    • computed、watch、methods
  • Object.freeze :冻结对象
  • 使用ui组件按需引入

INFO

  • 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 ,图片服务器。
  • 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
  • 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
  • 当需要设置的样式很多时设置className而不是直接操作style。
  • 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
  • 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
  • 图片预加载,将样式表放在顶部,将脚本放在底部 加上时间戳。

第五章 面试题兼容篇

5.1 页面样式兼容

  • 在ios键盘中首字母大写的问题?
    • <input type="text" autocapitalize='off'>
  • ios日期转换NAN问题
    • 具体就是,new Date('2020-11-12 00:00:00')在ios中会为NAN
    • 解决方案:用new Date('2020/11/12 00:00:00')的日期格式,或者写个正则转换
  • 在移动端使用click事件有300ms延迟的问题
    • 禁止双击缩放===》meta:user-scalabel=no
  • 移动端touch事件有穿透(点透)的问题,怎么解决?
    • 阻止默认行为 : e.preventDefault();
    • fastclick.js
  • 安卓部分版本input的placeholder偏上

    -input{ line-height:normal; }

第六章 面试题网络请求篇

6.1 跨域面试题

  • 前端:jsonp、vue的项目可以设置代理(打包后无效。解决:.ENV文件)
  • 后端:CORS

6.2 http 和 https 的区别?

  • 端口不同

    • http :80端口
    • https :443端口
  • https比http更加安全

  • ***https就是证书

6.3 HTTP 缓存 https://blog.csdn.net/weixin_46318413/article/details/122676866

第七章 WEB 安全篇

7.1 XSS 攻击

  • 用户输入的文本框,需要替换某些特殊字符( <> ... )

7.2 SQL 注入

  • 用户输入的文本框中不可以有特殊符号( 引号、空格 )

7.3 接口安全

7.4 其他(https://mp.weixin.qq.com/s/RgTO5c-Px8UgRw9fQjM8Qw)

第八章 其他类面试题

8.1 token

  • token是后端生成的
  • token + cookie : 前端判断是否过期
  • token + localStorage : 后端判断是否过期给前端返回code码,前端判断code码等于多少

8.2 SEO

  • 网站一定要多页面
  • title、描述、关键字
  • 图片、音频、视频、的标签属性特别关键
  • 网站不能出现死链接

第九章 其他

9.1 前后端不分离

  • 优点:

    • seo会特别好
    • 人员成本下降(后端就可以做了)
    • 无需请求接口,压力在服务器,如果服务器比较好,用户打开网页速度比分离的要快。( 但是有一个问题,是整个网页打开或者不打开 )
  • 缺点:

    • 项目不好维护(项目大)
    • 如果网页没出来,后端是不可以套数据的

9.2 前端和后端分离

  • 优点: 项目好维护( 分责任 )

  • 缺点:

      1. 人员成本会高
      1. seo 不好 ===>有对应解决方案的 【预渲染和服务端渲染】
      1. 如果接口请求次数特别多,并且没办法优化合并请求,用户打开网页速度就会慢
  • 本身:

      1. 网页先出来
      1. 请求接口
      1. 接口数据放在页面上
  • 预渲染:

      1. 请求接口
      1. 接口数据放在页面上
      1. 网页先出来
  • 服务端渲染:

      1. nodejs服务 请求接口
      1. 后端服务给nodejs返回数据
      1. nodejs服务,把数据给client
      1. 打开页面

9.3 补充预渲染和服务端渲染区别

  • 预渲染(prerender-spa-plugin)

    • 实现原理:相当于 html 预备加载,但是要等数据完成后
    • 请求接口数据
    • 打开页面
    • 场景: 1. 如果一个网站,不是所有页面都做 seo,可以用。 2. 他不支持动态路由 3. 动态的 title 描述关键词
  • 服务端渲染 : SSR

    • 实现原理:相当于多了一个后端服务
      1. nodejs服务 请求接口
      1. 后端服务给nodejs返回数据
      1. nodejs服务,把数据给client
      1. 打开页面
  • 场景: 1. 整个网站都做 seo,可以实现动态 title 2. 多页面 3. 可以数据爬去

  • 缺点 : 不支持 localStorage、cookie

  • SSR:服务端渲染,指的是服务端直接吐出具有数据的 HTML 页面,而不是在客户端拼接的 HTML。相对的则是 CSR(客户端渲染),客户端渲染指的是在客户端通过 Ajax 请求来拼装数据,此时所有页面是在客户端拼接好的

9.4vue 权限验证怎么说

  • 角色管理
  • 我们那个角色是分两大模块的
  • 一个是根据角色划分权限的
  • 一个是自定义权限
  • 角色是指普通员工 经理级之类的 我需要做的就是角色管理 可以增加的就是副经理之类的岗位 可以做增删改查,然后每一个角色根据类型不同是需要划分菜单的,然后有做一个用户管理,商品管理 供应商管理 地图管理之类的,这个菜单是动态路由,动态加载进来的 在角色管理有个权限分配,比如说分配一个经理 它具有商品管理 订单管理的权限 那这几块选上以后他登录进去就有这三块管理的功能
  • 自定义管理就是一些特殊的权限 比如张三的角色是一个经理 ,可能它具有商品管理 订单管理等但他还需要地图管理之类的 这时候就需要单独的勾选了

9.5 你前端是怎么学的

  • 面试官问怎么学前端的,这种问题考察什么?总结四个字:学习能力

  • 面试官想知道以下内容:

  • 学习能力
  • 总结能力
  • 动手能力(这个也是面试官最想知道的,毕竟学以致用)

INFO

可以这样回答: 一开始学习前端,主要靠视频以及书籍,主要是总结很多知识点,但是发现学习过程中理论大于实操,所以自己把知识点总结后就开始找项目实操,这样一步一步成长起来的,那么在公司中也会碰到很多问题值得学习,一般都是自己查找原因或者和同事交流进行解决,然后自己总结出文档,方便日后查看和积攒经验。所以我感觉我的学习都是实操加总结。