一本正经前端面试清单

/ 前端 / 1 条评论 / 8045浏览

HTML模块

1.标签语义化作用

见标签知其意,让代码结构清晰,方便阅读,有利于其他设备解析。例如:屏幕阅读器、盲人阅读器,遵循W3规范以语义化标签渲染网页更利于搜索引擎的优化(SEO),网络不佳时(无样式),网页也更具可读性,常见的语义化标签如下mian、aside、footer、code、article、section等标签。

2.常见浏览器内核

浏览器内核负责对网页语法进行解析,即内部的渲染引擎,决定网页的显示效果,常见的内核有以下几种:

  1. IE浏览器,微软出品的Trident内核,厂商前缀-ms-;

  2. Chrome,谷歌出品的Webkit内核,已经转向Blink内核,厂商前缀-webkit-;

  3. Firefox,Mozilla出品的Gecko内核,厂商前缀-moz-;

  4. 欧朋浏览器,欧朋出品的Presto内核,厂商前缀-o-;

  5. Safari,苹果出品的Webkit,厂商前缀-webkit-;

3.<image>标签title与alt属性的区别

alt标签是图片无法正常显示时对图片的描述;title为设置该属性的元素提供建议性的信息,鼠标悬停在元素上时会提示文字信息。

4.HTML和XHTML的区别

XHTML是可以拓展的超文本标签语言,更严格更纯洁的HTML语言,具有以下的特点:

  1. XHTML标签必须被正确的嵌套;

  2. XHTML标签存在闭合;

  3. 标签名必须小写;

  4. XHTML必须拥有根元素;

5.iframe的优缺点

优点
缺点

6.常见文档类型和DOCTYPE

doctype一般声明于html文件的第一行,作用是告诉浏览器以哪一个文档类型进行解析文本,如果不存在则以包容模式解析具体的文档类型,常见有以下几种文档类型:

  1. Standards (标准)模式用于呈现遵循最新标准的网页;

  2. Quirks(包容兼容)模式用于呈现为传统浏览器而设计的网页;

7.HTML5 <!DOCTYPE HTML>

HTML5不基于SGML标准通用标记语言,则不需要DTD 文档类型定义引用,但是需要DOCTYPE规范浏览器行为,而HTML4基于SGML,需要引用DTD,文件第一行进行如下声明<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">定义HTML文档。

8.使用link和@import导入样式的区别

可以通过link和@import引入CSS资源文件,但是具有一下的不同点:

  1. 性质不同,link是xhtml标签,无兼容性问题,可用于加载CSS文件的同时还可以进行RSS信息聚合等事务,而@import属于CSS范畴,在CSS2时提出,低版本浏览器不支持,只能用于加载CSS文件;

  2. 加载时间不同,link引用CSS随页面载入时同时加载,@import需要在页面加载完毕后被需要时才会加载;

  3. 写法不同,link是写在head标签中,而@import在html中只能写在style标签中;

  4. 样式权重不同,link引用的样式权重高于@import;

9.无样式内容闪烁(FOUC)

无内容闪烁英文称为Flash of Unstyle Content,@import需要在页面加载完毕后被需要时才会加载,因此页面DOM加载完成到CSS导入完成之间会有一段时间页面上的内容是没有样式,解决方法是使用在head中使用link标签加载CSS样式表,文档按顺序载入,body渲染完成后link早已加载完成,所以不会出现FOUT问题。

10.浏览器内核引擎

浏览器内核主要分成两部分,渲染引擎和JS引擎,渲染引擎负责页面内容(HTML、XML、图像等)输出到网页中,浏览器的内核不同渲染的效果也不同;JS引擎则是解析和执行javascript进而实现网页的动态效果,且两者越来独立化。

11.HTML5中manifest离线缓存

<html manifest='cache.manifest'>开启离线缓存,当浏览器发现HTML头部有manifest属性,进行请求manifest文件,首次访问浏览器就会根据manifest文件的内容下载相应的资源并进行离线存储。如果资源没有发生改变,则浏览器直接读取manifest中离线缓存的文件进行渲染,具体文件内容如下:

CACHE MANIFEST
CACHE:
/logo.gif
NETWORK:

FALLBACK:
offline.html

12.页面可见性API用途

通过监听visibilityState的属性值进行检测页面是否可见以及打开网页时的一些日志,根据监听document的visibilitychange事件检测用户是否切屏,锁屏,退出等状态,用于切换页面则视频停止播放等场景。

13.src和href区别

href标识超文本引用,用于link和a等元素应用,通过href将当前元素和引用资源之间建立联系;src表示引用资源替换当前元素用在img、script、iframe,无跨越问题,<script src="js.js"></script>当浏览器解析时会暂停其他资源的下载和处理,常说的将引用js文件时要放在body的最底部的原因于此。

14.输入框autocomplete

浏览器会自动记录同名(name)input框中的值,并在用户输入时会提示造成数据的泄露不安全,通过给标签设置autocomplete为off来取消此功能,IE浏览器需要在internet选项菜单中里的自动完成里面设置。

15.浏览器离线持久化存储

浏览器可以通过cookie、ssessionStorage、localStorage进行对数据进行存储,同源策略下均可以访问,但具有一下不同点:

  1. 性质不同,cookies是为了标识用户身份而存储用户本地终端上的数据,自动在同源http请求头中携带,cookies在浏览器和服务器间来回传递信息,而sessionstorage和localstorage不会自动把数据发给服务器,仅在本地保存;
  2. 存储大小的限制不同,cookie仅可以保存4Kb且数量不超过20条,sessionstorage和localstorage保存的数据可达到5M;
  3. 生命周期不同,cookie可以设置生命周期且在过期之前均有效,sessionstorage仅在浏览器窗口关闭或者页面之前有效,若不手动删除localstorage则永久有效;
  4. 作用域不同,cookie和localStorage在所有的同源标签页(不同页面但域名端口相同)都是共享,而不同标签页面的sessionStorage不共享;

16.label标签作用

label 标签来定义表单控件之间的关系,for属性值与一个控件a的id一致时,点击label标签,控件a会获得焦点,将控件包裹在label标签中就省去for和id的对应关系。

17.网页验证码作用

  1. 区分用户是计算机还是程序;
  2. 防止恶意破解密码和刷票行为;

18.meta标签viewport的理解

<meta></meta>元素可提供有关页面的元信息并且仅存在与head标签内,设置viewport视口<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">使文档宽度等于设备的真实屏幕的宽度,同时可控制用户的缩放行为,缩放是相对于文档宽度等于屏幕宽度而言,即1css的代表更多的物理像素。场景化分析,如果不添加meta的视口标签,那么在iPhone6中你设置一个375px的div,浏览器默认整文档宽度是980px,所以会出现左右的滚动条,设置视口标签那么默认是文档的宽度等于屏幕的宽度,所以375px恰好可以撑满屏幕。

19.HTML5新特性

  1. 语义化标签;
  2. 丰富input中type类型;
  3. 音频(audio)和视频(video);
  4. 拖放API;
  5. 地理位置;
  6. canvas画布;
  7. svg;
  8. webWorker;

20.HTML页面的渲染过程

  1. 浏览器解析HTMLl源码标签,根据标签嵌套创建DOM树,并行加载静态资源文件,每一个HTML标签都是文档树中的一个节点,构成了由documentElement节点为根节点的DOM树;
  2. 浏览器解析CSS代码,计算得出样式数据,构建CSSOM树,非法的语法被直接忽略掉,解析CSS的时候按照顺序来定义优先级浏览器默认设置 < 用户设置 < 外链样式 < 内联样式 < !important的规则进行解析;
  3. DOM树和CSSOM树组成渲染树并绘制渲染树到屏幕上;
  4. 如果渲染树中的节点被移除、位置改变、元素的显示隐藏等属性改变都会重新执行上面的流程,这一个行为称为回流;与重绘不同,重绘是渲染树上的某一个属性需要更新且仅影响外观、风格,不影响布局,例如:修改background-color就属于重绘只是重新绘制到屏幕中上,回流必定造成重绘;

CSS模块

1.BFC规则

块级元素格式化上下文,英文Block Formatting Contexts,一个独立的渲染区域与外界元素不会相互影响,它规定了其内部的块级元素如何进行布局。

触发BFC条件
  1. float属性存在且值不为none;
  2. display: inline-block | table-cell | table-caption | flex | inline-flex;
  3. overflow存在且值不为visible;
BFC特性
  1. 两个相邻且触发BFC规则的元素在垂直方向上margin不会重叠;
  2. 元素排布默认是按垂直方向排布;
  3. BFC规则的高度值浮动元素也会参与计算,这也是父元素设置overflow:hidden;可以清除浮动的缘由;
  4. 两个BFC规则区域不会发生重叠;

总而言之,bfc规则是一个隔离的独立容器,子元素与外面的元素互不影响,当BFC区域的位置变化不会影响其子元素的内部布局,bfc区域的高度是包含浮动元素的高度,进而不会影响外部的布局;如果是普通的块级元素在垂直方向上是会发生margin重叠的现象,且margin的实际值取决于两个元素之间的最大值。

2.LFC规则

元素默认占满屏幕宽度,直到屏幕宽度不够时发生折行显示,无法设置宽高,元素的高度取决于内容的大小和padding的水平值,为元素设置display: inline;时就会形成LFC规则。

3.常见行内元素和块级元素

行级元素
  1. 当屏幕还有空间时默认占满屏幕而不会发生折行;
  2. 无法设置宽高;
  3. 仅水平方向上的margin和padding有效;

常见的行级元素标签:input、img、a、span、textarea、label、code、select,可通过display: flex | block转换成为块级标签。

块级元素
  1. 垂直排布;
  2. 可以设置宽高;

常见的块级元素标签:address、caption、div、dd、form、h、br、ul、table,可通过display: inline;转变成为行级标签。

4.一行展示元素

设置元素的float、inline-block以及父元素设置为flex弹性布局,浮动float可以但需要注意清除浮动。

5.清除浮动方式

  1. 需要清除浮动的区域增加一个新的元素(div);

  2. 需要清除元素设置clear:both,它的左右就不会存在浮动元素;

  3. 利用伪元素::before来在元素内部插入两个元素块,注意一定要设置content:""

6.box-sizing盒模型

标准情况下即box-sizing:content-box,盒子的实际宽高 = width/height+ padding + border + margin;而在怪异盒模型即box-sizing:border-box,盒子的实际宽高 = width/height + margin,设置的padding和border不再单独参与盒子宽高的计算中,而是width/height = padding + border + 内容部分,超出时盒子会被撑开。

7.CSS中的hack

由于不同厂商的不同版本对CSS的支持解析不一样,则会导致不同浏览器所呈现出的效果不同,针对不同的浏览器版本写特定的CSS样式,这个过程就叫CSSHask,不推荐Hack写法,因为那是因为浏览器兼容性的补救行为,其中CSSHack的分类有:

/* 属性前缀法,在CSS样式属性名前添加一些特定浏览器能识别的前缀,通过javascript检测IE10后给html标签加上class=”ie10“的类名。 */
.ie10 #hack{
	color:red; /* Only works in IE10 */
}
*background-color: blue;

/* 属性前缀法,在CSS样式属性名前添加一些特定浏览器能识别的前缀。 */
-ms-high-contrast: none

/* IE条件注释法,这个方式IE浏览器专有的hack方式。 */
<!--[if IE]>
	只在IE浏览器显示
<![endif]-->

8.nth-of-type | nth-child的区别

<style>
  /* ul下的第二个li标签 */
  ul li:nth-of-type(2) {
    color: red;
  }
  /* ul的li标签且是第二个孩子所以匹配不到元素 */
  ul li:nth-child(2) {
    color: gold;
  }
</style>

<ul>
  <p>p元素</p>
  <span>span元素</span>
  <li>li元素</li>
  <li>li元素</li>
  <li>li元素</li>
</ul>

9.理解:before 和 ::before 区别

单冒号用于CSS3中的伪类,双冒号用于CSS3的伪元素,伪元素的本质创建了一个有内容的虚拟容器,不存在与dom树中,伪类本质上是弥补CSS选择器的不足。CSS2和CSS3都存在属性的作用一样,因此:before和::before的是一致的效果。

/* 伪元素 */
ul::after {
  content: "我爱你";
}

/* 伪类 */
a:hover {
  color: gold;
}

10.元素水平垂直居中

无宽高
  1. 绝对定位和translate;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
  1. 为其父元素设置为flex水平垂直轴居中;
display: flex;
align-items: center;
justify-content: center;
  1. 绝对定位和margin实现;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
有宽高:
  1. 为其父元素设置line-height=宽度配合text-align: center(仅限行级元素);
text-align: center;
line-height: 等于宽度;
  1. 绝对定位配合margin-left左右偏移
position: absolute;
left: 50%;
top: 50%;
margin-left: -200px;
margin-top: -200px;

11.手动实现placeholder

Js判断浏览器是否支持placeholder属性,根据样式选择器遍历获取到特定的input框,填充输入框并将字体设置成灰色,起到视觉上支持的效果,当用户点击获得焦点时清空提示信息,blur事件判断用户内容是否为空,如空则填回提示信息。

12.常见浏览器的兼容性问题

  1. png24位的图片在iE6浏览器上出现背景,通过转换成为PNG8解决;
  2. 不同浏览器默认的margin和padding不同,开局全域设置*{margin:0;padding:0;}统一效果;
  3. 超链接a标签访问后就不具有hover和active的效果,避免方式是改变CSS属性的排列顺序:L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}(重点);
  4. 上下margin重合问题,ie和火狐下相邻的div的margin-left和margin-right不会重合,但是margin-top和margin-bottom却发生重合;
  5. chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示,CSS 属性 -webkit-text-size-adjust: none; 进行解决;
  6. 图片默认有间隙,解决方式img标签添加display:block;
  7. 上下margin的重叠问题,解决方式转变成为BFC规则;

13.前端优化解决方案

  1. <link>代替@import;
  2. 避免使用滤镜;
  3. js和css代码压缩;
  4. 减少iframe标签;
  5. 使用体积更小的jpeg格式图片;
  6. CSS雪碧图;
  7. 懒加载;
  8. 避免重绘和回流;
  9. 减少http请求次数;
  10. 缓存策略;

14.media媒体查询属性

media属性用于为不同的屏幕媒介类型规定不同的样式,max-width:375px,屏幕大于375px时样式不生效,min-width:1024px,屏幕大于1024px时样式才生效。

15.meta标签name值

name 属性主要用于描述网页信息与之对应的content的内容主要是便于搜索引擎机器人查找信息和分类信息,主要分为以下几个参数:

  1. keyword,描述网站的关键字说明;
  2. description,描述网站内容;
  3. robots,机器人导向,告诉需要索引的页面;

16.px/em/rem区别

  1. em值不固定,em继承父元素的字体大小,em代表父容器的倍数当标签层层嵌套时需要修改某一个标签的em值需要重新计算;
  2. rem值不固定,rem相对与根元素(html)元素的字体大小,浏览器1rem默认是16px;
  3. px值固定,px在页面缩放时无法进行调整;

这也是为什么给font-size设置62.5%值,因为浏览器默认的字体高度是16px,未调整时1rem等于16px,不好进行判断,设置字体为62.5%时,1rem=10px,比较容易计算。

17.sass和scss的区别

  1. 文件拓展名不同,sass文件使用的是*.sass,scss文件的拓展名是*.scss;
  2. 书写语法不同,sass 是以严格的缩进式语法规则书写且不带大括号{}和分号,要通过软件进行编译转换成为css样式。scss语法跟css相似且通过可以嵌套写法,通过&可以选择上级元素;

19.标签a点击虚框问题解决

a,a:hover,a:active,a:visited,a:link,a:focus{ 
 -webkit-tap-highlight-color:rgba(0,0,0,0);
 -webkit-tap-highlight-color: transparent;
 outline:none;
 background: none;
 text-decoration: none;border:none;
 -webkit-appearance: none;
}

21.CSS制作三角形

使用border可以实现,边框的执行赋值顺序是上、右、下、左的顺时针,设置一个宽高为0的区域,设置宽度大一些,就会出现正方形,在通过设置颜色,就能出现拼盘效果,再给对应的边的颜色设置为透明即可。

<style>
  .d1 {
    width: 0;
    height: 0;
    border-width: 100px;
    border-color: red orange blue blueviolet;
    border-color: transparent transparent blue transparent;
    border-style: solid;
  }
</style>
<body>
  <div class="d1"></div>
</body>

22.理解使用transform变形

transform可以定义元素很多静态样式实现变形倾斜(skew)、旋转(rotate)、缩放(scale)、位移(translate)以及透视(perspective)等功能,几个主要参数:

  1. translate3d(x,y,z)位移;
  2. scale3d(x,y,z)缩放;
  3. rotateX(180deg)旋转;
  4. skewX(30deg)倾斜;
  5. perspective(500px) 3D转换元素提供透视;
  6. transition 整个动画执行的时间;

23.理解使用transition动画

默认情况下CSS属性的变化是瞬间完成的可以控制transition让变化过程平滑,但是不是所有的css属性都支持动画特效,一般来说具有中间值的属性是可以存在动画。简单写法:transition: 2s;动画过程是2s,其他省略的属性全部是默认值,有以下控制值:

  1. transition-property,默认值为all即所有的属性均参与动画,可以自定义动画的属性;
  2. transition-duration: 3s,定义动画过程的时间,可以设定两个时间,根据顺序分给需要设定设定动画的属性值;
  3. transition-timing-function:ease,ease是指动画先快后慢,设置动画的过渡效果;
  4. transition-timing-function:steps(n,start),设置步进的速度,将整一个动画分为n个时间点,动画不会延迟;
  5. transition-delay:1s,动画延迟一秒执行;

24.理解使用animation关键帧

transition过渡动画是两个状态间的变化,帧动画可以处理动画过程中不同时间的细节变化,对每一帧进行处理,也可以把帧动画理解为多个帧之间的过渡动画。也不是所有的css属性都具有动画,具有以下属性:

  1. animation-name:动画1,动画2,可以定义多个动画;
  2. animation-duration:动画时间,可以设定多个值并分给上面的动画;
  3. animation-iteration-count:infinite,默认动画仅执行一次,设置infinite后循环执行;
  4. animation-direction:normal,动画的方向,默认是从0%到100%运行动画,设置alternate则会先从0%到100%,然后从100%到0%,添加reverse则相反效果;
  5. animation-delay:1s,动画延迟时间;
  6. animation-timing-function: ease-in,动画的指向速率;
  7. animation-play-state:paused动画的暂停播放;
  8. animation-fill-mode:forwards,动画执行完成之后的状态,设置forwards则会停留在最后一帧;
div {
  animation-name: 动画名, scale;
  animation-duration: 3s; 
}

@keyframes 动画名 {
  from {
    // 第一帧的状态特效
  }
	
  25% {
    // 整个动画的1/4节点上的特效状态
  }
  50% {
    // 整个动画的2/4节点上的特效状态
  }
  to {
    // 最后一帧的状态特效
  }
}

25.自适应布局方法

考察绝对定位和浮动的理解

  1. float+margin(适应横向布局)
<title>左右固定 中间自适应</title>
<style>
  .left {
    width: 100px;
    height: 500px;
    background-color: red;
    float: left;
  }

  .right {
    width: 100px;
    height: 500px;
    background-color: #00f;
    float: right;
  }

  .center {
    height: 500px;
    margin: 0 200px;
    background-color: #f0f;
  }
</style>

  1. float+绝对定位(适应横向布局)
<title>左右固定 中间自适应</title>
<style>

  .left {
    width: 200px;
    height: 500px;
    background-color: red;
    float: left;
  }

  .right {
    width: 200px;
    height: 500px;
    background-color: #00f;
    float: right;
  }

  .center {
    height: 500px;
    position: absolute;
    left:200px;
    right:200px;
    background-color: #f0f;
  }
</style>

  1. 绝对定位+绝对定位(适应横向布局)
<title>左右固定 中间自适应</title>
<style>

  .left {
    width: 200px;
    height: 500px;
    position: absolute;
    left: 0px;

  }

  .right {
    width: 200px;
    height: 500px;
    position: absolute;
    right: 0px;
  }

  .center {
    height: 500px;
    position: absolute;
    left:200px;
    right:200px;
    background-color: #f0f;
  }
</style>
  1. 圣杯布局(绝对定位+float)
<style>
.container {
  height: 500px;
  overflow: hidden;/*清除浮动 */
}

.main {
  height: 500px;
  background-color: #f0f;
  left: 200px;
  right: 200px;
  position: absolute;
}

.left {
  width: 200px;
  height: 500px;
  background-color: red;
  left: 0px;
  float: left;
}

.right {
  width: 200px;
  height: 500px;
  background-color: #00f;
  float: right;

}

.head,
.foot {
  width: 100%;
  height: 50px;
  background: yellow;
}
</style>

26.常用列表符号

标签分为有序列表ol和无序列表ul,可以通过type属性列表符号进行修改,常用有以下几种符号:

  1. circle空心圆;
  2. disc实心圆;
  3. square实心方块;
  4. decimal数字;
  5. 罗马符号;
  6. 大小写字母;

27.CSS高度塌陷

父元素无宽高设置且无内容时,子元素设置浮动的属性则会脱离文档流,父盒子高度为零的现象称为CSS高度塌陷,需要进行清除浮动处理。

28.display

  1. block,将标签变为块级标签;
  2. inline,将标签变为行级标签;
  3. flex,将标签变成弹性盒子;
  4. inline-block,将标签变为行级块标签;
  5. table等相关布局,将标签渲染成table标签;

29.常见选择器

  1. 标签选择器a {}
  2. class选择器.name{}
  3. 通用选择器*{}
  4. id选择器#name{}
  5. 属性选择器input[name=sex]{}
  6. 伪类选择器:hover {}
  7. 结构选择器p>a{}

30.CSS3新特性

  1. 新增动画相关特性transform/transition/animation
  2. 新增选择器结构选择器/伪类选择器/属性选择器
  3. 边框阴影;
  4. 背景background-size/background-clip
  5. box-sizing

31.移动端常用布局方式

  1. flex,弹性盒子模型;
  2. rem,移动端布局;
  3. gird,栅格布局;

JavaScript模块

1.理解掌握闭包

一个函数对其周围状态(变量)的引用并保存周围变量,乃至函数执行完成后仍然可以访问的现象称之为闭包,闭包让外部访问函数内部的变量成为可能(私有属性),因为被引用的数据常驻内存,可能会造成内存泄露(一块内存长期被变量占据而不进行释放),闭包可以让你在一个内层函数中访问到其外层函数的作用域的状态并保存,在js中每当创建一个函数,闭包环境就在函数创建时产生,闭包环境相互独立,如果闭包环境引用外部函数作用域的一个变量a,即使当外部函数作用域的变量被销毁释放内存,但变量a不会被删除。

// 第一题
function funA(){
  var a = 10;  // funA的活动对象之中;
  return function(){   //匿名函数的活动对象;
        alert(a);
  }
}
var b = funA();
b();  //10

// 第二题

function outerFn(){
  var i = 0; 
  function innerFn(){
      i++;
      console.log(i);
  }
  return innerFn;
}
var inner = outerFn(); 
inner();
inner();
inner();
var inner2 = outerFn();
inner2();
inner2();
inner2(); //1 2 3 1 2 3

// 第三题
var i = 0;
function outerFn(){
  function innnerFn(){
       i++;
       console.log(i);
  }
  return innnerFn;
}
var inner1 = outerFn();
var inner2 = outerFn();
inner1();
inner2();
inner1();
inner2();     //1 2 3 4

// 第四题
function fn(){
	var a = 3;
	return function(){
		return  ++a;                                     
	}
}
alert(fn()());  //4
alert(fn()());  //4 

// 第五题
function outerFn(){
var i = 0;
  function innnerFn(){
      i++;
      console.log(i);
  }
  return innnerFn;
}
var inner1 = outerFn();
var inner2 = outerFn();
inner1();
inner2();
inner1();
inner2();    //1 1 2 2

// 第六题
(function() { 
  var m = 0; 
  function getM() { return m; } 
  function seta(val) { m = val; } 
  window.g = getM; 
  window.f = seta; 
})(); 
f(100);
console.info(g());   //100  闭包找到的是同一地址中父级函数中对应变量最终的值

//第七题
function a() { 
  var i = 0; 
  function b() { alert(++i); } 
  return b; 
} 
var c = a(); 
c();      //1 
c();      //2

// 第八题
function f() { 
  var count = 0; 
  return  function() { 
      count++; 
      console.info(count); 
  } 
} 
var t1 = f();
t1();     //1 
t1();     //2 
t1();     //3

// 第九题
var add = function(x) { 
  var sum = 1; 
  var tmp = function(x) { 
      sum = sum + x; 
      return tmp;    
  } 
  tmp.toString = function() { 
      return sum; 
  }
  return tmp; 
} 
alert(add(1)(2)(3));     //6

// 第十题
var lis = document.getElementsByTagName("li");
for(var i=0;i<lis.length;i++){
  (function(i){
      lis[i].onclick = function(){
           console.log(i);
      };
  })(i);       //事件处理函数中闭包的写法
} 

// 第十一题
function m1(){
     var x = 1;
     return function(){
          console.log(++x);
     }
}
 
m1()();   //2
m1()();   //2
m1()();   //2
 
var m2 = m1();
m2();   //2
m2();   //3
m2();   //4

// 第十二
var  fn=(function(){
   var  i=10;
   function  fn(){
      console.log(++i);
   }
   return   fn;
})() 
fn();   //11
fn();   //12

// 第十三
function love1(){
     var num = 223;
     var me1 = function() {
           console.log(num);
     }
     num++;
     return me1;
}
var loveme1 = love1();
loveme1();   //输出224

2.未声明和未定义的理解

未声明的变量是程序中不存在且未声明的变量,访问未声明的变量会进行报错;未定义的变量是在程序中声明但尚未给出任何值的变量,访问不会报错并得出undefined值。

3.理解全局变量

声明变量时省略关键字就会造成变量污染

4.定时器

延时一段时间并执行任务,因为它是宏任务,需要等待微任务执行完成后才可以执行,当设置一个等待时间为零的定时器它也不会立即执行,欺骗感情!

5.相等符号”==“和”===“区别

  1. ===称为严格等式运算符,两个操作数比较前不会进行类型转换,如果数据类型不同就直接定为不同;
  2. ==包容等式运算符,两个操作数比较前如果发现数据类型不一样,则转换成数据相同的数据类型再比较,不同则不同;

6.隐式转换?

逻辑运算符"=="进行两个是比较是否相等时,不同的数据类型会造成隐式转换后再比较,属于js中比较难的部分,具体情况如下:

  1. 数组和布尔值比较,[] == true;//false,空数组转为""再转为0,逻辑值true直接转为1;
  2. 数组符串比较,[1,2,3] == '1,2,3' // true,[1,2,3]转换成字符串"1,2,3"最后跟字符串比较;
  3. 字符串和数字进行比较,'1' == 1 // true,字符串转为数字后与数字1比较;
  4. 字符串和布尔值进行比较,'1' == true; // true,字符串转为数字1,布尔值转为数字1,比较相等;
  5. 布尔值和数字比较,true == 1;/ true,布尔值转为数字1再比较;

有趣的事情是[] == false和![] == false的结果都是true,第一个[]数组转为""再转成0,false直接转为0,比较相等;第二个同理,!符号优先级高所以先执行,所以式子就变成(![]) == false,估计就能理解了!另外有几个比较的特殊undefined == null // trueNaN == XXX //NaN和任意类型都不等(包括自己)

7.常见逻辑值假的值

js中空字符串""、NaN、undefined、null、flase,0,逻辑值为假,但是空数组[]、空对象{}逻辑值为真。

8.基本数据类型

  1. 基础数据类型:undefined、null、String、Number、Boolean、Symbol;
  2. 复杂数据类型:数组、对象;

9.New操作符流程

  1. 创建了一个新的空对象{};

var obj = new Object()

  1. 设置新对象obj的__proto__ = 构造函数.prototype

obj.__proto__ = 构造函数.prototype

  1. 构造函数中的this指向新对象a;

Var res = 构造器.call(obj),因为函数存在闭包所以每一个作用域都是相互独立,就有了对象的概念。

  1. 属性访问器中的setter中进行判断,如果是对象(引用类型则返回),否则返回空对象{}

10.节流和防抖

前端开发中我们经常需要绑定一些持续触发的函数,例如:跳转屏幕宽度resize,监听页面滚动scroll,拖拽mousemove。这些过程中绑定的函数频繁的触发,所以节流和防抖就很好的解决办法。

  1. 防抖debounce,指触发事件触发后的n秒内又被触发,则会重新计算时间,例如设置300毫秒的防抖时间,事件触发后的300毫秒内该事件又被触发,则重新计算时间,又将等待300毫秒。如果三百毫秒内没有触发,则直接执行事件的处理程序;
// 体验代码
<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>
<script>
    let num = 1;
    let content = document.getElementById('content');

    function count() {
        content.innerHTML = num++;
    };
    content.onmousemove = count;
</script>


function debounce(func, wait = 200) {
    let timeout; // 定义定时器
    return function () {
        let context = this; // 获取当前函数的指向者
        let args = arguments; // 获取到传递的参数对象
        if (timeout) clearTimeout(timeout); // 如果等待时间内又触发了事件,则将之间的定时器去掉,重新进行定时。
				
        timeout = setTimeout(() => {
            func.apply(context, args) // 将回调函数绑定给函数执行者并传入参数
        }, wait);
    }
}
  1. 节流throttle,连续触发事件,但是在n秒内只是执行一次处理程序,体现效果每200毫秒会执行事件的处理程序;
function throttle(func, wait = 200) {
  let timeout; // 定义定时器对象
  return function () {
    let context = this; // 获得函数执行对象
    let args = arguments; // 获得参数
    // 定时器为空时开启 不为空则还有定时任务 不执行处理函数
    if (!timeout) {
      // 开启定时任务
      timeout = setTimeout(() => {
        timeout = null; // 等待定时成功后将time赋值为空值
        func.apply(context, args);
      }, wait);
    }
  };
}

11.理解this指针

this简单的理解就是指向某一个作用域的指针,有以下几个场景与this指针相关:

  1. 默认绑定,当函数调用时无任何调用前缀的情景,成为默认绑定此时this是指向全局对象window(非严格模式),严格模式下指向undefined,但是严格模式下调用不在严格模式中的函数是不会影响this指向;
  2. 隐式绑定,函数调用者持有this,如果函数调用时存在前缀,那么this就会被绑定到前缀的对象上;
function doA() {
  console.log(this);
}
let obj = {
  name: "huasen",
  func: doA
}
obj.doA() // this指向obj
  1. 显示绑定,通过call、apply、bind可以更改this的行为,更能感知this指向变化过程;
let obj1 = {
    name: 'call'
};
let obj2 = {
    name: 'apply'
};
let obj3 = {
    name: 'echo'
}
var name = '花森';

function fn() {
    console.log(this.name);
};
fn(); // 花森
fn.call(obj1); // call
fn.apply(obj2); // apply
fn.bind(obj3)(); // echo
  1. new操作符绑定,通过构造函数new调用函数时,js以构造函数的prototype属性为原型创建一个新对象,this指向新对象,this和参数传递给构造器执行,构造器自动返回一个对象;
  2. 箭头函数中this,不适用与上面介绍的绑定规则,准确来说箭头函数中的this指向当前作用域的父级作用域,一旦箭头函数的this绑定成功,将无法再次修改,取一个名字,称为硬绑定;

12.ES6新增特性

  1. let和const;
  2. 字符串拓展,include(是否包含子串)、startsWith(子串是否首部)等函数;
  3. 解构表达式;
  4. 箭头函数;
  5. Promise;
  6. set和map;
  7. 模块化export和import模块化导入导出;
  8. 对象拓展,keys,values方法;
  9. find数组方法;

13.继承几种方式

// 原型链继承
Cat.prototype = new Animal();

// 构造继承,使用借用构造函数,通过call构造函数传入数据将父类的实例属性绑定到当前实例this。
function Cat(name){
  Animal.call(this); // 可以传入数据
  this.name = name || 'Tom';
}

// 遍历拷贝继承,遍历父类的属性并赋值给子类的原型对象,注意深浅拷贝问题。
function Cat(name){
  var animal = new Animal();
  for(var key in animal){
    Cat.prototype[key] = animal[key];
  }
  this.name = name || 'Tom';
}
// 寄生组合继承
function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
(function(){
  // 创建一个没有实例方法的类
  var Super = function(){};
  Super.prototype = Animal.prototype;
  //将实例作为子类的原型
  Cat.prototype = new Super();
})();

// class继承
class Cat extends Animal {
  constructor() {
    
  }
}

14.处理异步任务方式

  1. 回调函数(callback)
function A(callback){
    console.log("I am A");
    callback();  // 传入函数
}
  1. Promise
new Promise((resolve,reject) => {
  resolve("成功处理");
})
  1. 订阅者发布者模式

15.null和undefined区别

null代表空值代表空对象指针,没有对象此处不应该有值,对象原型链的终点;undefined代表声明但未赋值的变量,undefined是一个预设的全局变量。

typeof undefined //  undefined
typeof null // object
null == undefined // true
undefined + 6 // NaN
null + 6 // 6

16.数组去重

// ES6利用set去重
Array.from(new Set(arr))

// for嵌套for+splice截掉去重
for() {
  for() {
    if(arr[i] == arr[j]) {
      arr.splice(j,1);
      j--;
    }
  }
}
    
// indexOf去重
arr.map((item)=> {
  if(arry.indexOf(item) == -1) {
    array.push(item);
  }
})

17.原型链

由构造函数prototype原型对象通过__proto__连接组成的一条指针链路就指原型链

18.require 和 import

require是AMD的引入方法,require是运行时调用,引入资源将赋值给某一个变量;import是ES6的语法标准,编译时调用所以必须放在文件开头,import引入资源是属于结构过程。

19.常见HTTP请求

  1. get;
  2. put;
  3. post;
  4. delete;
  5. head;
场景GETPOST
点击返回按钮刷新无影响重新提交表单
缓存/添加书签可以缓存不可缓存
历史记录没有
编码类型application/x-www-form-urlencodedapplication/x-www-form-urlencoded 或 multipart/form-data
是否幂等幂等非幂等
长度限制浏览器限制长度理论没有限制但是服务器配置或内存限制
数据类型限制只能ASCII没有限制且允许二进制数据
安全性拼接于URL中request body传递数据
可见效可见不可见

19.同源策略

http协议中规定同协议、同域名、同端口简称为同源策略,同源策略是为了互联网的安全,例如:网站A是无法访问到网站B所存入的cookie信息,因为不符合同源策略的标准。

20.常见跨域方式

  1. jsonp;
  2. document.domain,二级域名和顶级域名的资源共享,两个页面设置同样的document.domain属性可以实现跨域;
  3. window.name,页面中打开页面后window.name任然存在且可以访问;
  4. postMassage,html5新增接口,多窗口中的信息传递;
  5. 跨域资源共享CORS,服务器端Access-Control-Allow-Origin设置可以通过的源,前端页面如果需要接收服务器带回的Cookie信息,需要打开xhr.withCredentials = true;确定请求是否携带Cookie;
  6. nginx反向代理;

21.常见设计模式

  1. 工厂模式;
  2. 观察者模式;
  3. 混合模式;

22.禁止事件冒泡

事件冒泡现象点击点击子元素,父元素的click事件同样会触发,使用event.stopPropagation()阻止冒泡。

23.阻止默认事件

存在href属性的a标签被点击后,默认会跳转页面,form表单中类型为submint的input框被点击后默认提交表单,这一个现象称为默认行为,可以通过event.preventDefault()阻止。

24.标签a伪类设置顺序

排列顺序:L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}

25.标签a禁止跳转

e.preventDefault()href="javascript:void(0)可以实现

26.中断ajax请求方式

  1. 请求时间超时自动停止ajax请求;
  2. 调用XML对象的abort方法进行手动停止;

27.事件代理理解

事件委托是指将事件绑定到目标元素的父元素上,利用事件的冒泡机制触事件;好处是节省内存的开销以及对新增加的元素节点同样生效。

28.事件属性target和currentTarget理解

  1. target被点击触发事件的元素;
  2. currentTarget捕获到到并执行程序的元素;

29.宏任务和微任务理解

执行顺序是同步代码>微任务>宏任务,程序执行,限制执行同步代码,遇到微任务(resolve())进入微任务队列中,优先执行微任务,遇到宏任务进入函数调用栈中的指向的任务成为宏任务,按顺序弹出执行;一次CPN轮询下,先执行同步代码,将微任务队列中的任务全部执行完成,再按顺序执行函数调用栈中的宏任务。

30.get和post请求区别

  1. 传参数的方式不同,get是通过URL明文传参,post请求参数不可见,存在与http的请求体;
  2. 传递的大小不同,get请求参数拼接在url后面,传递长度受限制,post请求传递的长度没有限制;
  3. 编码方式不同,get只是支持URL编码和ASCLL字符编码,post可以进行多种编码方式;
  4. 健壮性不同,get请求回退不会重新发送,post请求回退后重新提交表单;

31.常见响应状态码

浏览器输入网址打开网页时,浏览器会向服务器发送请求后会收到服务器返回的一个响应报文,报文中的存在有HTTP状态码的头信息。浏览器通过状态码进行一系列操作,状态码反应当前请求的状态。

常见状态码
  1. 200正常请求;
  2. 301资源(网页等)被永久转移到其它URL;
  3. 404请求的资源(网页等)不存在;
  4. 500内部服务器错误;
状态码分类
分类分类描述
1**信息提示(服务器收到请求但需要请求者继续执行操作)
2**成功(操作被成功接收并处理)
3**重定向(需要进一步的操作以完成请求)
4**客户端错误(请求包含语法错误或无法完成请求)
5**服务器错误(服务器在处理请求的过程中发生了错误)
数字英文名称中文描述
100Continue继续(应继续请求)
101Switching Protocols切换协议(服务器根据客户端的请求切换协议)
200OK请求成功(一般用于GET与POST请求)
201Created已创建(成功请求并创建了新的资源)
202Accepted已接受(接收请求但未处理完成)
203Non-Authoritative Information非授权信息(请求成功但返回的meta信息不在原始的服务器)
204No Content无内容(服务器成功处理但未返回内容)
205Reset Content重置内容(服务器处理成功且用户终端(例如:浏览器)应重置文档视图)
206Partial Content部分内容(服务器成功处理了部分GET请求)
300Multiple Choices多种选择
301Moved Permanently永久移动(请求的资源已被永久的移动到新URI但返回信息会包括新的URI且浏览器会自动定向到新URI
302Found临时移动(但源只是临时被移动)
303See Other查看其它地址(使用GET和POST请求查看)
304Not Modified未修改(协商缓存时资源未修改)
305Use Proxy使用代理
307Temporary Redirect临时重定向
400Bad Request客户端请求的语法错误(服务器无法理解)
401Unauthorized请求要求用户的身份认证
402Payment Required保留(将来使用)
403Forbidden服务器理解请求客户端的请求(但是拒绝执行此请求)
404Not Found服务器无法根据客户端的请求找到资源(网页)
405Method Not Allowed客户端请求中的方法被禁止
406Not Acceptable服务器无法根据客户端请求的内容特性完成请求
407Proxy Authentication Required请求要求代理的身份认证
408Request Time-out服务器等待客户端发送的请求时间过长
409Conflict服务器完成客户端的 PUT 请求时可能返回此代码
410Gone客户端请求的资源已经不存在
411Length Required服务器无法处理客户端发送的不带Content-Length的请求信息
412Precondition Failed客户端请求信息的先决条件错误
413Request Entity Too Large由于请求的实体过大
414Request-URI Too Large请求URL过长(URI通常为网址)
415Unsupported Media Type服务器无法处理请求附带的媒体格式
416Requested range not satisfiable客户端请求的范围无效
417Expectation Failed服务器无法满足Expect的请求头信息
500Internal Server Error服务器内部错误
501Not Implemented服务器不支持请求的功能
502Bad Gateway从远程服务器接收到了一个无效的响应
503Service Unavailable由于超载或系统维护(服务器暂时的无法处理客户端的请求且延时的长度可包含在服务器的Retry-After头信息中)
504Gateway Time-out充当网关或代理的服务器(未及时从远端服务器获取请求)
505HTTP Version not supported服务器不支持请求的HTTP协议的版本

Vue模块

1.理解MVVM模型

MVVM是model-View-ViewModel的缩写,其中model代表数据模型是业务操作的基础;View代表视图层,界面UI组件负责展示数据;ViewModel监听数据模型的改变和控制视图行为。MVVM架构中数据模型和视图分离,数据模型仅与ViewModel进行双向交互,View数据变化会同步传入ViewModel中,进而改变数据模型的值,同理数据模型的改变也会间接反映到View视图层上。ViewModel通过双向绑定把view视图和Model数据模型连接,同步操作自动完成,复杂的数据状态完全由MvvM统一管理。

2.理解Vue生命周期

实例从创建到销毁的过程就叫生命周期,从开始创建,初始化数据,编译解析模板,挂载DOM并渲染,循环监听更新渲染,销毁实例等一系列过程。

  1. beforeCreate创建前,数据观测和初始化事件未开始;
  2. create创建后完成数据观测属性和方法的运算,初始化事件,$属性没有被挂载渲染出来;
  3. beforeMount挂载前,实例挂载el对象前被调用,render函数首次被调用,完成模板编译,data里面数据和模板生成fragment片段,但是还没有被挂载到html文档上去,尚不能操作进程DOM节点获取操作;
  4. mounted挂载后,替换原来el并挂载到实例上去,以及可以获取到DOM节点,可进行ajax交互,节点进行实践监听等操作;
  5. beforeUpdate更新前,数据更新前调用,发生在虚拟DOM重新渲染和打好补丁之前,不会触发附加的重渲染过程;
  6. updated更新后,数据更新导致虚拟DOM重新渲染,数据以及更新完毕;
  7. beforeDestroy销毁前,vue实例销毁前调用,此时仍然可以访问使用;
  8. destroyed销毁后,vue实例销毁后调用,事件监听以及组件实例都被销毁;

3.理解Vue实现数据双向绑定的原理

vue实现数据双向绑定的主要是采用数据劫持结合发布者订阅者者模式的方式,通过definedProperty()定义属性特征以及属性访问器getter/setter进行数据拦截,当数据发生变动时进入getter访问器,通过notify()通知订阅者,触发回调update方法更新数据视图。vue的双向绑定将MVVM作为绑定数据的入口,整合Observer,Compile和Watcher三者,开局Observe监听自己数据变化生成发布者,通过Compile解析模板指令,生成属性订阅者。

4.理解组件之间参数传递

  1. 父组件向子组件传值,父组件使用子组件时设置属性,子组件内部通过props方法接收数据;
  2. 子组件向父组件传值,子组件内部使用$emit方法发生事件,父组件在子组件上监听并绑定该方法,取得数据;
  3. 非父子关系时,创建一个事件中心,通过事件总线的方式通信;
  4. VUE实现父子组件之间的数据交互;

5.理解Router中mode

Vue路由是通过hash和HTML5新增history进行实现前端路由,更新视图但不重新发起请求页面是前端路由的核心理念,目前浏览器环境中存在以下两种方式:

  1. URL中的hash值('#');

hash值用于指示网页中文档的位置,通过window.location.hash属性读取,虽然URL改变,但不会包括在HTTP请求中,用于指示浏览器完成动作,不会造成页面刷新,每次访问都会在历史访问记录中增加一个记录。拥有两个方法push和replace方法,push直接对window.location.hash,调用window.location.replace方法将路由进行替换。

  1. 利用history;

History interface是浏览器历史记录栈提供的接口,通过back()、forward()、go()可以读取和操作历史记录,新增的接口提供pushState()、replaceState(),浏览器跳转到新的状态,触发popState事件。调用修改历史记录栈后当前URL没有改变,浏览器也不会发送请求。

6.vue/angular/react区别

  1. 相同点,vue和angular都支持内置指令和自定义指令,支持过滤器数据双向绑定。vue和安react的中心思想相似,react采用特殊的JSX语法,vue组件化开发中也推崇使用.vue文件,vue文件的使用理解更为直接。一切皆为组件,声明周期过程都提供合理的钩子函数;
  2. 不同点,angular增加特性,依赖对脏数据的检测,所以当Watcher订阅者越多越慢。vue提供的api相对简单直观,采用的依赖追踪,并且使用异步队列更新,所有的数据都是独立触发。React采用虚拟dom对渲染结果做脏数据检测,想比来说vue更方便快捷的操作虚拟dom;

7.导航守卫

首页可以控制导航跳转,beforeEach,afterEach导航守卫,可以对页面title进行修改,页面访问权限的控制,例如:登录后才可以访问某些页面等效果实现,beforeEach和afterEach都是存在三个主要参数,to、from、next()以下就是详细的介绍:

  1. to代表route即将进入的页面;
  2. from代表正要离开的页面;
  3. next函数需要在beforEach调用,否则会对路由对象进行拦截导致报错导致无法跳转;

8.理解Vuex工作场景

vuex是应用状态数据的存放仓库,具有State、Getter、Mutation、Actions、Module属性,其中mutation提交数据存储的同步任务,Action是处理异步逻辑的任务,新建store目录,index.js文件中使用Vue.use使用store对象,最后配置export导出,mian.js文件中引入Store,注入Store就可以在任意组件中通过this.$store.state引用到仓库内的数据。

  1. State仓库,vuex使用单一状态树,每一个应用最好仅包含一个store实例,不建议直接修改state的值,最好是通过commit方法调用mutation任务进行修改,方便后期数据的追踪;
  2. Mutations,定义方法动态修改state中的数据,不建议包含逻辑业务处理,处理一些同步任务;
  3. Actions,定义方法执行异步任务一些复杂的逻辑代码,view层通过store.dispath分发Action任务;
  4. Getter,类似vue实例中的计算属性特点,用来过滤规范改造数据;
  5. Module,项目特别复杂的时候使用,每一个模块拥有自己的state,mutation,Action,getter,代码逻辑更加清晰;

9.Vue-cli自定义指令

// 注册全局自指令 `v-focus`
Vue.directive('focus', {
  // 绑定的dom节点
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})


// 局部新增指令`huasen`
var app = new Vue({
    el: '#app',
    // 注册多个指令
    directives: {
        huasen: {
            inserted(el) {
                el.style.width = '200px';
                el.style.height = '200px';
            }
        }
    }
})

// 使用指令
<div v-focus></div>
<div v-huasen></div>

10.自定义过滤器

// 局部声明
const app = new Vue({
	el: "#app",
	data: {
		msg: ""
	},
	filters: {
		capitalize: function(value) {
			return "huasen"+value;
		}
	}
})
// 全局
Vue.filter("huasenjio",function(value){})

// 使用
<div>{{msg|capitalize}}</div>

11.理解keep-alive

keep-alive是Vue内置的一个组件,包含的组件保留状态,避免被重新渲染,keep-alive加入两个属性,include(包含)和exclude(排除)且exclude优先级大于include,可以通过正则表示式或者字符串定义。

<keep-alive include="XXX" exclude="XXX">
  组件
</keep-alive>

12.简要作答题

  1. css只在当前组件起作用,因为style标签中写入scoped进行限制则不会穿透,如果是渲染markdown语法则使用常规选择符将不会生效,需要使用>>> 进行穿透选择;
  2. v-if是按照条件是否渲染,v-show按照条件隐藏显示,但还存在与文档流中,类似于控制css中的display属性设置为none;
  3. $router是路由实例对象,包含路由的跳转方法,钩子函数,而$route是活跃路由信息对象,指向正在展示的活跃路由的信息,包含pah,params等信息;
  4. vue的两个核心是数据驱动和组件系统;
  5. 事件修饰符,prevent阻止事件默认行为,stop阻止点击事件冒泡行为,self事件仅在触发元素上发生,capture事件捕获,once触发一次,native绑定原生click;
  6. v-on可以绑定多个方法;
  7. vue中遍历时key的作用为每一个节点做唯一标识,v-for更新已渲染过的元素列表时,出于优化性能采用"就地复用策略",当当数据项的顺序被改变,Vue不会移动DOM元素来匹配数据项的顺序,而是简单复用每一个元素,key的作用就是更新dom,从而不要复用,避免获得脏数据结果;
  8. vue的计算属性调用时仅写计算属性名,获取数据并按一定规则输出,计算属性和method不同。不管依赖的数据是否变化,method都是从新计算,计算属性则是从缓存中读取,优化性能;
  9. vue具有简单的API实现数据绑定以及响应,核心是一个响应的数据绑定系统,MVVM架构,组件化开发,轻量等优点,但是vue不支持低版本的浏览器,目前仅支持到IE9,不利于SEO的优化,首屏加载时间较长;
  10. 路由通过path/:id属性后面添加冒号和便利的形式,使用时通过params.id获取;
  11. v-for具有更高的优先级,意味者遍历的时候每个元素都进行if判断,造成内存的浪费,所以不建议使用v-for和v-if指令;
  12. push();pop();shift();unshift();splice(); sort();reverse();数组方法修改后数据能够发生响应式,但是通过索引修改则不可以数据响应式;

13.理解$nextTick

this.$nextTick()回调函数延迟到下次 DOM 更新循环之后执行,tick回调会等待DOM更新或者生成之后使用,常用于页面交互,后台获取数据后生成dom对象操作后执行,tick中回调函数会等待渲染完成后再进行调用。

14.SPA和多页面应用区别

单页面应用(SPA)程序仅有一个入口,首屏加载时间相对较长,一旦加载完成后用户体验很好,减少服务器的压力,但是不利于SEO,多页面应用程序有多个入口,页面跳转是整页进行刷新。

16.assets和static区别

两者都是存放静态资源文件,但是又存在细微差别,assets资源文件存放的资源文件项目打包时会对静态资源文件进行处理,修改名字改变类型等操作,而static则是直接拷贝到打包文件夹中,没有经过压缩处理。template需要的样式文件都可以放在asset中,压缩代码体积,第三方静态文件库可以放static中。

17.delete和Vue.delete删除数组区别

delete只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变,Vue.delete 直接删除了数组。

18.理解Vue-router和location.href区别

使用window对象的location.href='/url'来跳转简单方便,但是页面会造成刷新,Vue-router采用的是HTML5的history.pushState('/url')方法进行跳转,不会造成页面刷新。

19.理解Vue中的slot插槽

插槽常用于组件封装中,组件具有一定布局,但内容元素相似,可以使用插槽预留位置,使用插入对应的DOM,vue内部会自动进行替换。

20.如何监听组件上点击事件

router-link阻止触发click事件,使用使用@click.native直接监听原生事件。

21.Axios拦截器原理

Axios是基于Promise机制实现的异步的链式请求框架,引用场景,接口请求前拦截对数据进行处理,请求带上所需参数判断token是否过期,axios框架create创建的实例设置interceptors拦截器,可以在入口文件main.js将实例对象绑定给vue原型,设为全局。

22.路由懒加载

通过const home = () => import("XXX"),webpack会将动态引入的模块单独分割成为一个文件,文件名字默认是从0开始以数字进行命名。

23.Vue新特性

  1. 支持UI界面构建项目;
  2. 重写虚拟DOM;
  3. 优化插槽;

24.Vue项目优化思路

  1. 路由组件懒加载;
  2. 减少使用watch数据;
  3. 循环时设置key标识;
  4. 用户体验优化(节流防抖);
  5. cdn引入第三方库;

26.Computed和Watch

computed是计算值,简化模板中{{}}的代码,具有缓存性,页面重新渲染值不会变化,不必再次执行函数;watch是观察监听数据的动作,无缓存性,页面重新渲染时不变化也会执行。

27.常用事件修饰符

  1. stop,阻止冒泡;
  2. prevent,阻止默认事件;
  3. capture,事件捕获模式;
  4. self,触发事件执行;
  5. once,只触发一次;
// 示例
<a @click.stop="getName()"></a>

28.弃用definedProperty改用Proxy的理解

Object.defineProperty对单个属性进行监听且不能监听属性的增加和删除,通过索引修改数组元素不可以进行监听,不可以在属性访问器中使用对象,否则造成死循环;Proxy则监听的整个对象,实现了目标对象的响应式。

WebPack模块

1.gulp/grunt 与 webpack的区别

Grunt/Gulp属于一类的都是打包构建工具,Webpack 是目前最热门的前端资源模块化管理和打包工具,gulp基于任务和流,而webpack是基于入口文件,根据关系依赖引入文件,根据依赖图进行打包。

2.常见的Loader

  1. file-loader文件统一输出到指定文件夹,HTML中通过相对路径引用文件;

  2. url-loader文件很小的情况下以 base64 的方式把文件内容注入到代码中;

  3. babel-loader把 ES6 转换成 ES5;

  4. css-loader加载 CSS;

  5. style-loader把 CSS 代码注入到 JavaScript 中;

  6. eslint-loader通过 ESLint 检查 JavaScript 代码;

3.Loader和Plugin不同

  1. loader意思作为加载解析文件作用,实现的功能比较小,默认webpack仅可以打包json和js语法,通过安装loader可以加载识别更多文件。plugin是插件,更为灵活实现的功能更广泛;
  2. loader使用前需要安装,不需要引入可直接在module.rules中配置。plugin则需要安装,引入模块,使用时需要new 实例对象;

4.webpack的构建流程?

  1. 初始化参数,从配置文件和 Shell 语句中读取与合并配置参数;
  2. 开始编译,通过配置参数初始化 Compiler 对象,加载配置的插件,执行对象的 run 方法开始执行编译;
  3. 确定入口,根据配置中的 entry 找出入口文件;
  4. 编译模块,入口文件出发,调用所有配置的 Loader 对模块进行翻译;
  5. 完成模块编译,使用 Loader 翻译完所有模块后得到模块之间的依赖关系图;
  6. 输出资源,根据入口和模块之间的依赖关系,引入模块组合成为Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,此处可以修改输出文件;
  7. 输出完成,确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统;

8.理解webpack的HMR热更新

可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块

9.理解webpack来优化前端性能

  1. 开发环境优化,DevServer开发工具优化,实现HMR热替换,采用多线程编译;
  2. 生产环境优化,代码分隔配合CDN引入资源,使用ES6语法引入,实现Tree shaking效果,通过压缩代码缩小体积,通过source-map进行源文件和资源文件的映射方式,内联方式可以提高性能;

前端安全

  1. XSS跨站脚本攻击,用户的输入值没有严格控制导致,用户发布信息中插入脚本,导致当其他用户打开时自动执行脚本,污染网络环境,解决方法是对输入数据进行过滤转义,传输数据采用特殊编码;
  2. CSRF (Cross-site request forgery)跨站请求伪造,网站将重要信息放置于浏览器本地,解决办法是在关键的业务点进行验证码验证,还可以判断请求头中referer属性判断连接是否是合法页面发起;
  3. sql注入,URL中携带对数据的操作参数,解决办法对URL数据进行处理转义;
  4. 文件上传漏洞;

设计模式

JavaScript中类的概念,基于JS中闭包与弱类型形成的伪类,设计模式和其他语言略微不同,设计原则如下:

  1. 单一职责原则(SRP),一个对象方法仅实现一个功能,如果承担过多职责,需求变动则改写的可能性很大;
  2. 最少知识原则(LKP),尽量避免对象之间直接交互,设置第三方进行处理;
  3. 开放/封闭原则(OCP),软件实体具有拓展性但不可修改,增添功能可以采用增加代码的方式,尽量避免改动源代码;

单例模式

思想是一个类仅有一个实例对象,并且实现全局访问,多次实例对象和修改均无效。

// 一个管理者类
function Manager(name) {
    this.manager = name;
}
// 定义管理者类的原型方法
Manager.prototype.getName = function() {
    console.log(this.manager);
};
// 定义生成单例的函数
var SingletonManager = (function() {
    var manager = null; // 绑定于window对象实现全局访问
		// 返回函数(工厂模式生成)
    return function(name) {
        if (!manager) {
            manager = new Manager(name); // 生成实例返回
        }

        return manager;
    } 
})();

SingletonManager('a').getName(); // a
SingletonManager('b').getName(); // a
SingletonManager('c').getName(); // a

// 封装抽离单例函数
function getSingleton(fn) {
    var instance = null;

    return function() {
        if (!instance) {
            instance = fn.apply(this, arguments); // 使用传入的构造函数生成对象
        }
        return instance;
    }
}

// 使用示例
var managerSingleton = getSingleton(function(name) {
    var manager = new Manager(name);
    return manager;
});

managerSingleton('a').getName(); // a
managerSingleton('b').getName(); // a
managerSingleton('c').getName(); // a

策略模式

定义系列算法并封装,使其可以相互替换。核心思想就是将算法的使用和算法的实现分开,一个基于策略模式的程序,至少两个部分组成:

  1. 策略类,封装具体算法并负责计算过程;
  2. 环境类,接收请求并委托给策略类;
// 加权映射关系
var levelMap = {
    S: 10,
    A: 8,
    B: 6,
    C: 4
};

// 组策略
var scoreLevel = {
    basicScore: 80,
    S: function() {
        return this.basicScore + levelMap['S']; 
    },

    A: function() {
        return this.basicScore + levelMap['A']; 
    },

    B: function() {
        return this.basicScore + levelMap['B']; 
    },

    C: function() {
        return this.basicScore + levelMap['C']; 
    }
}

// 环境组
function getScore(level) {
    return scoreLevel[level] ? scoreLevel[level]() : 0;
}

console.log(
    getScore('S'),
    getScore('A'),
    getScore('B'),
    getScore('C'),
    getScore('D')
); // 90 88 86 84 0

代理模式

迭代器模式

发布/订阅模式

核心思想是定义对象间的一种一对多的依赖关系,当发布者发生改变则会通知所有依赖的对象,取代对象之间硬编码的通知机制,发布者不需要显示的调用依赖对象的接口,js中通常使用注册回调函数形式实现发布订阅者模式。

// 订阅click事件
document.body.addEventListener('click', function() {
    console.log('click1');
}, false);

document.body.addEventListener('click', function() {
    console.log('click2');
}, false);

// 发布
document.body.click(); // click1  click2

命令模式

模板方法模式

享元模式

职责链模式

中介者模式

装饰者模式

状态模式

适配器模式

外观模式

GIT协同