欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前端面试整理

程序员文章站 2022-04-22 19:01:47
...

一、CSS

1.两个盒子,一个下边据20px,一个上边据30px,最后为两个盒子之间的距离为多少?

答案:30px

2.什么是高度坍塌

在文档流中,父元素的高度默认是由子元素撑开的,但是我们把子元素设置为浮动后,子元素完全脱离文档流,此时子元素无法撑起父元素的高度,导致父元素高度坍塌。

3.高度坍塌的解决方法(清除浮动的方法)

给父元素设置高度 缺点:只适用于父元素高度固定的情况下。

给父元素也设置浮动样式(如float: left 缺点:给父元素设置浮动样式后,父元素的父元素也会产生高度坍塌问题。

给父元素设置overflow: hidden;overflow: auto 缺点:设置hidden会导致超出部分直接被隐藏,且不占据文档流位置,而设置auto的话超出部分会生成一个滚动条,影响视觉效果。

增加块级元素并设置clear: both属性 缺点:增加无意义的标签

<style>
  .container {
    background: lawngreen;
  }

  .box1 {
    background: red;
    height: 100px;
    width: 300px;
    float: left;
  }

  .box2 {
    float: left;
    background: rebeccapurple;
    height: 200px;
    width: 300px;
  }

  .clear {
    clear: both;
  }
</style>

<div class="container">
  <div class="box1"></div>
  <div class="box2"></div>
  <div class="clear"></div>
</div>
复制代码

使用伪元素after 推荐使用这种方法

<style>
  .container {
    background: lawngreen;
  }

  .clear {
    zoom: 1;
  }

  .clear:after {
    clear: both;
    content: '';
    display: block;
    visibility: hidden;
    height: 0;
  }

  .box1 {
    background: red;
    height: 100px;
    width: 300px;
    float: left;
  }

  .box2 {
    float: left;
    background: rebeccapurple;
    height: 200px;
    width: 300px;
  }
</style>

<div class="container clear">
  <div class="box1"></div>
  <div class="box2"></div>
</div>
复制代码

4.伪类和伪元素的区别

伪类和伪元素的根本区别在于:它们是否创造了新的元素(抽象)。从我们模仿其意义的角度来看,如果需要添加新元素加以标识的,就是伪元素,反之,如果只需要在既有元素上添加类别的,就是伪类。

  • CSS 伪类用于向某些选择器添加特殊的效果。

     

    前端面试整理

     

  • CSS 伪元素用于将特殊的效果添加到某些选择器。

     

    前端面试整理

     

5.src和href的区别

  • href是Hypertext Reference的缩写,表示超文本引用。用于在当前文档和引用资源之间确立联系。。当浏览器解析到该元素时,不会停止对当前文档的处理
  • src是source的缩写,src的内容是页面必不可少的一部分,是引入。src指向的内容会嵌入到文档中当前标签所在的位置即替换当前元素。当浏览器解析到该元素时,会暂停浏览器的渲染,直到该资源加载完毕。

这是为什么我们经常把CSS放在<head></head>标签之间,而把JS放在body的最底部的原因。

6.两侧宽度固定,中间自适应

设置左右设置float: leftfloat: right,中间使用margin-leftmargin-right 缺点:三个元素没有按照常规顺序排列,中间center的元素一定要放在最后

<style>
  .container {
    background: #fff;
  }

  .left {
    background: red;
    float: left;
    width: 200px;
    height: 100px;
  }

  .right {
    background: blue;
    float: right;
    width: 300px;
    height: 200px;
  }

  .center {
    background: rebeccapurple;
    height: 200px;
    margin-right: 300x;
    margin-left: 200px;
  }
</style>

<div class="container">
  <div class="left"></div>
  <div class="right"></div>
  <div class="center"></div>
</div>
复制代码

两侧使用绝对定位,中间使用margin-left,和margin-right 缺点:top的值需要根据页面上的其它内容确定

<style>
  .container {
    background: #fff;
  }

  .left {
    background: red;
    width: 200px;
    height: 100px;
    position: absolute;
    top: 0;
    left: 0;
  }

  .center {
    background: rebeccapurple;
    height: 200px;
    margin-left: 200px;
    margin-right: 300px;
  }

  .right {
    background: blue;
    width: 300px;
    height: 200px;
    position: absolute;
    top: 0;
    right: 0;
  }
</style>

<div class="container">
  <div class="left"></div>
  <div class="center"></div>
  <div class="right"></div>
</div>
复制代码

父元素使用两端对齐方式display: flex,中间宽度设置为width: 100%

<style>
  .container {
    background: #fff;
    display: flex;
  }

  .left {
    background: red;
    width: 200px;
    height: 100px;
  }

  .center {
    background: rebeccapurple;
    height: 200px;
    width: 100%;
  }

  .right {
    background: blue;
    width: 300px;
    height: 200px;
  }
</style>

<div class="container">
  <div class="left"></div>
  <div class="center"></div>
  <div class="right"></div>
</div>
复制代码

margin负值法:左右两栏均左浮动,左右两栏采用负的margin值。

<style>
  html,
  body {
    padding: 0;
    margin: 0;
  }

  .container {
    background: #fff;
    float: left;
    width: 100%;
  }

  .left {
    background: red;
    width: 200px;
    height: 100px;
    float: left;
    margin-left: -100%;
  }

  .center {
    background: rebeccapurple;
    height: 200px;
    margin-left: 200px;
    margin-right: 300px;
  }

  .right {
    background: blue;
    width: 300px;
    height: 200px;
    float: left;
    margin-left: -300px;
  }
</style>

<div class="container">
  <div class="center"></div>
</div>
<div class="left"></div>
<div class="right"></div>
复制代码

7.em和rem的区别

ps: px绝对度量单位,就是像素,是屏幕能显示出的最小的一个点

rem的特点

  • rem的大小是根据html根目录下的字体大小进行计算的。
  • 当我们改变根目录下的字体大小的时候,下面字体都改变。
  • rem不仅可以设置字体的大小,也可以设置元素宽、高等属性。

em的特点:

  • 字体大小是根据父元素字体大小设置的。

8.css 选择器过长怎么判断他的优先级:

内联样式1000 -- id100 -- 类、伪类、属性选择器10 -- 类型选择器、伪元素选择器1 通过相加计算大的优先级高,值相等的话后声明的优先级高。

9.CSS怎么实现垂直居中

绝对定位与负边距实现 缺点:需要知道div的高度和宽度

<style>
  .center {
    position: relative;
    background-color: rebeccapurple;
    height: 200px;
    width: 200px;
  }

  .box .content {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 20px;
    height: 40px;
    margin-left: -10px;
    margin-top: -20px;
    background-color: aqua;
  }
</style>

<div class="box center">
  <div class="content"></div>
</div>
复制代码

绝对定位与margin

<style>
  .center {
    position: relative;
    background-color: rebeccapurple;
    height: 200px;
    width: 200px;
  }

  .box .content {
    position: absolute;
    width: 20px;
    height: 40px;
    background-color: aqua;
    margin: auto;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
  }
</style>

<div class="box center">
  <div class="content"></div>
</div>
复制代码

使用CSS3的transform属性

<style>
  .center {
    position: relative;
    background-color: rebeccapurple;
    height: 200px;
    width: 200px;
  }

  .box .content {
    position: absolute;
    width: 20px;
    height: 40px;
    background-color: aqua;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
</style>

<div class="box center">
  <div class="content"></div>
</div>
复制代码

使用flex布局

<style>
  .center {
    background: rebeccapurple;
    height: 200px;
    width: 200px;
  }

  .box {
    display: flex;
    justify-content: center;
    align-items: Center;
  }

  .content {
    background-color: aqua;
    width: 20px;
    height: 40px;
  }
</style>

<div class="box center">
  <div class="content"></div>
</div>
复制代码

使用table-cell 缺点:只支持行内元素inline或inline-block,可将块级元素设为inline-block

<style>
  .center {
    background: rebeccapurple;
    height: 200px;
    width: 200px;
  }

  .box {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
  }

  .content {
    background-color: aqua;
    width: 20px;
    height: 40px;
    display: inline-block;
  }
</style>

<div class="box center">
  <div class="content"></div>
</div>
复制代码

display:flex和margin:auto

<style>
  .center {
    background: rebeccapurple;
    height: 200px;
    width: 200px;
  }

  .box {
    display: flex;
    text-align: center;
  }

  .content {
    background-color: aqua;
    width: 20px;
    height: 40px;
    margin: auto;
  }
</style>

<div class="box center">
  <div class="content"></div>
</div>
复制代码

10.CSS3新特性

border-radius 、box-shadow、border-image、text-shadow、word-wrap、transform、@media、flex

11.display的值

 

前端面试整理

 

常用:

 

  • none:此元素不显示。
  • block:将元素显示为块级元素,前后会带换行符。
  • inline:默认值,元素会被显示为内联元素,前后没有换行符。
  • inline-block:行内块级元素。

12.去除inline-block元素间的空格

  • 去掉HTML中的空格
<div class="space">
    <a href="##">
    惆怅</a><a href="##">
    淡定</a><a href="##">
    热血</a>
</div>
或者是:
<div class="space">
    <a href="##">惆怅</a
    ><a href="##">淡定</a
    ><a href="##">热血</a>
</div>
或者是借助HTML注释:
<div class="space">
    <a href="##">惆怅</a><!--
    --><a href="##">淡定</a><!--
    --><a href="##">热血</a>
</div>
复制代码
  • margin 负值
.space a {
    display: inline-block;
    margin-right: -3px;
}
复制代码
  • 省略闭合标签
<div class="space">
    <a href="##">惆怅
    <a href="##">淡定
    <a href="##">热血</a>
</div>
注意,为了向下兼容IE6/IE7等浏览器,最后一个列表的标签的结束(闭合)标签不能丢。
复制代码
  • 使用font-size: 0
.space {
    font-size: 0;
    -webkit-text-size-adjust:none;   //兼容部分浏览器
}
复制代码

13. CSS超出文本隐藏并显示省略号

单行文本省略

  .ellipsis-line {
    width: 400px;
    overflow: hidden;
    text-overflow: ellipsis; //文本溢出显示省略号
    white-space: nowrap; //文本不会换行
  }
复制代码

多行文本省略

.multi-line {
    border: 1px solid #f70505;
    width: 400px;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}
复制代码

利用定位和伪类元素

p{
    position: relative; 
    width:400px;
    line-height: 20px; 
    max-height: 60px;
    overflow: hidden;
}
p::after{
    content: "..."; 
    position: absolute; 
    bottom: 0; 
    right: 0; 
    padding-left: 40px;
    background: -webkit-linear-gradient(left, transparent, #fff 55%);
    background: -o-linear-gradient(right, transparent, #fff 55%);
    background: -moz-linear-gradient(right, transparent, #fff 55%);
    background: linear-gradient(to right, transparent, #fff 55%);
}
复制代码

14.元素不可见

{ display: none; /* 不占据空间,无法点击 */ } 

{ visibility: hidden; /* 占据空间,无法点击 */ } 

{ position: absolute; top: -999em; /* 不占据空间,无法点击 */ } 

{ position: relative; top: -999em; /* 占据空间,无法点击 */ } 

{ position: absolute; visibility: hidden; /* 不占据空间,无法点击 */ } 

{ height: 0; overflow: hidden; /* 不占据空间,无法点击 */ } 

{ opacity: 0; filter:Alpha(opacity=0); /* 占据空间,可以点击 */ } 

{ position: absolute; opacity: 0; filter:Alpha(opacity=0); /* 不占据空间,可以点击 */ } 
复制代码

15.渐进增强和优雅降级

渐进增强(progressive enhancement):针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。(从被所有浏览器支持的基本功能开始,逐步地添加那些只有新式浏览器才支持的功能,向页面添加无害于基础浏览器的额外样式和功能。当浏览器支持时,它们会自动地呈现出来并发挥作用。)

.transition{
  -webkit-transition: all .5s;
     -moz-transition: all .5s;
       -o-transition: all .5s;
          transition: all .5s;  
}
复制代码

优雅降级(graceful degradation):一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。(Web站点在所有新式浏览器中都能正常工作,如果用户使用的是老式浏览器,则代码会检查以确认它们是否能正常工作。由于IE独特的盒模型布局问题,针对不同版本的IE的hack实践过优雅降级了,为那些无法支持功能的浏览器增加候选方案,使之在旧式浏览器上以某种形式降级体验却不至于完全失效。)

.transition{ 
&emsp;&emsp;     transition: all .5s;
&emsp;&emsp;  -o-transition: all .5s;
  &emsp;-moz-transition: all .5s;
 -webkit-transition: all .5s;
}
复制代码

16.如何让图片按等比例放大缩小

<style>
  .box {
    width: 200px;
    height: 300px;
  }

  img {
    width: 100%;
    height: auto;
    max-width: 100%;
    max-height: 100%;
  }
</style>

<div class="box">
  <img src="./test.jpg" />
</div>
复制代码

17. CSS3动画性能优化

a) 尽可能多的利用硬件能力,使用3D开启GPU加速translate3d

b) 使用transform的translate替代margin或position中的top、right、bottom和left,同时使用transform中的scaleX或者scaleY来替代width和height

18. block,inline,inline-block的区别

  • display:block
    • block元素会独占一行,多个block元素会各自新起一行。默认情况下,block元素宽度自动填满其父元素宽度。
    • block元素可以设置width,height属性。块级元素即使设置了宽度,仍然是独占一行。
    • block元素可以设置margin和padding属性。
  • display:inline
    • inline元素不会独占一行,多个相邻的行内元素会排列在同一行里,直到一行排列不下,才会新换一行,其宽度随元素的内容而变化。
    • inline元素设置width,height属性无效。
    • inline元素的margin和padding属性,水平方向的padding-left, padding-right, margin-left, margin-right都产生边距效果;但竖直方向的padding-top, padding-bottom, margin-top, margin-bottom不会产生边距效果。
  • display:inline-block
    • 简单来说就是将对象呈现为inline对象,但是对象的内容作为block对象呈现。之后的内联对象会被排列在同一行内。比如我们可以给一个link(a元素)inline-block属性值,使其既具有block的宽度高度特性又具有inline的同行特性。

19. CSS高度是宽度的一半

.box {
    background-color: blue;
    width: 100%;
    height: 0;
    padding-bottom: 50%;
}
复制代码

20.盒模型

 

前端面试整理

 

 

content-box(W3C 标准盒模型)

属性width,height只包含内容content,不包含border和padding。

布局所占宽度Width: Width = width + padding-left + padding-right + border-left + border-right

布局所占高度Height: Height = height + padding-top + padding-bottom + border-top + border-bottom

border-box(IE 盒模型)

属性width,height包含border和padding,指的是content+padding+border

布局所占宽度Width: Width = width(包含padding-left + padding-right + border-left + border-right)

布局所占高度Height: Height = height(包含padding-top + padding-bottom + border-top + border-bottom)

21.性能动画方面,为什么用css3

  • 减少DOM的操作
  • 可以利用硬件资源加速,如使用3D变形来开启GPU加速

22.css3动画和jquery动画的差别是什么

  • 功能涵盖面,JS比CSS3大
  • 实现/重构难度不一,CSS3比JS更简单,性能调优方向固定
  • 对于帧速表现不好的低版本浏览器,CSS3可以做到自然降级,而JS则需要撰写额外代码
  • CSS动画有天然事件支持(TransitionEnd、AnimationEnd,但是它们都需要针对浏览器加前缀),JS则需要自己写事件
  • CSS3有兼容性问题,而JS大多时候没有兼容性问题

23. 自适应布局(响应式)

  • 通过media选择加载CSS
  • viewport
  • 相对大小的字体em、rem
  • 不使用绝对定位

24.link和@import的区别

  • 加载页面时,link标签引入的 CSS 被同时加载;@import引入的 CSS 将在页面加载完毕后被加载。
  • @import是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别;link标签作为 HTML 元素,不存在兼容性问题。
  • 可以通过 JS 操作 DOM ,插入link标签来改变样式;由于 DOM 方法是基于文档的,无法使用@import的方式插入样式。
  • @import是 CSS 提供的语法规则,只有导入样式表的作用;link是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等。

25.CSS预处理器Sass(Scss)、Less、Stylus

CSS预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为CSS增加了一些编程的特性,将CSS作为目标生成文件,然后开发者就只要使用这种语言进行编码工作。通俗的说,CSS预处理器用一种专门的编程语言,进行Web页面样式设计,然后再编译成正常的CSS文件

26.CSS hack

由于不同的浏览器对CSS的支持及解析结果不一样,还由于CSS中的优先级的关系。我们就可以根据这个来针对不同的浏览器来写不同的CSS。 a) 条件注释法 只在IE下生效

<!--[if IE]>
这段文字只在IE浏览器显示
<![endif]-->
复制代码

b) 类内属性前缀法

  • “-″减号是IE6专有的hack
  • “\9″ IE6/IE7/IE8/IE9/IE10都生效
  • “\0″ IE8/IE9/IE10都生效,是IE8/9/10的hack
  • “\9\0″ 只对IE9/IE10生效,是IE9/10的hack

27.line-height计算方法

line-height: normal;      // line-height=font-size*1.2 (默认为1.2)

line-height:inherit;&emsp;&emsp;&emsp;// 继承父元素

line-height:24px;&emsp;&emsp;&emsp;&emsp; // 通过像素px或者em等单位赋值

line-height:150%;&emsp;&emsp;     // line-height=font-size*1.5

line-height:1.5;&emsp;&emsp;&emsp;    // line-height=font-size*1.5

line-height:1.5em;&emsp;&emsp;&emsp;  // line-height=font-size*1.5
复制代码

二、HTML

1.viewport原理

  • 布局视口(layout viewport): 手机上为了容纳为桌面浏览器设计的网站,默认布局视口宽度远大于屏幕宽度,为了让用户看到网站全貌,它会缩小网站
  • 视觉视口(visual viewport): 屏幕的可视区域,即物理像素尺寸
  • 理想视口(ideal viewport): 当网站是为手机准备的时候使用。通过meta来声明。早期iPhone理想视口为320*480px

width=device-width指定了布局视口=理想视口,并且禁止缩放。所以添上width=device-widthviewport meta后页面变大了(一开始页面内容小得看不清),实际上是布局视口变小了。

2.HTML5新特性

<nav>、<article>、<header>、<section>、<footer>、<video>、<canvas>、draggable拖放、Input 类型color、date、datetime、datetime-local、email、month、number、range、search、tel、time、url、week

3.DOCTYPE的作用

DOCTYPE是docunment type(文档定义)的简写,用来说明web设计中所用的html或xhtml的类型,指出浏览器或者其他阅读程序按照什么样的规则

XHTML是XML重写了HTML的规范,比HTML更加严格,表现如下:

1、XHTML中所有的标记都必须有一个相应的结束标签

2、XHTML所有标签的元素和属性的名字都必须使用小写

3、所有的XML标记都必须合理嵌套

4、所有的**属性都必须用引号“”**括起来;

5、把所有<和&特殊符号用编码表示;

6、给所有属性附一个值

7、不要在注释内容中使用“--”;

8、图片必须使用说明文字

4.什么是语义化

语义化HTML:用最恰当的HTML元素标记的内容。

语义化是指用合理HTML标记以及其特有的属性去格式化文档内容。通俗地讲,语义化就是对数据和信息进行处理,使得机器可以理解.

5.HTML5 语义化标签

 <title></title>:简短、描述性、唯一(提升搜索引擎排名)
 <hn></hn>:h1~h6分级标题
 <header></header>:页眉通常包括网站标志、主导航、全站链接以及搜索框。
 <nav></nav>:标记导航,仅对文档中重要的链接群使用。
 <main></main>:页面主要内容,一个页面只能使用一次。如果是web应用,则包围其主要功能。
 <article></article>:包含像报纸一样的内容= =||是这么理解的,表示文档、页面、应用或一个独立的容器
 <section></section>:具有相似主题的一组内容,比如网站的主页可以分成介绍、新闻条目、联系信息等条块。
 <footer></footer>:页脚,只有当父级是body时,才是整个页面的页脚。
 <aside></aside>:指定附注栏,包括引述、侧栏、指向文章的一组链接、广告、友情链接、相关产品列表等。
 <small></small>:指定细则,输入免责声明、注解、署名、版权。
 <strong></strong>:表示内容重要性。
 <em></em>:标记内容着重点(大量用于提升段落文本语义)。
 <time></time>:标记时间。datetime属性遵循特定格式,如果忽略此属性,文本内容必须是合法的日期或者时间格式。   
 <address></address>:作者、相关人士或组织的联系信息(电子邮件地址、指向联系信息页的链接)。
 <code></code>:标记代码。包含示例代码或者文件名 (< &lt;  > &gt;)
复制代码

详细信息

6. HTML加载过程

网页渲染机制

解析 HTML 标签, 构建 DOM 树
解析 CSS 标签, 构建 CSSOM 树
把 DOM 和 CSSOM 组合成 渲染树 (render tree)
在渲染树的基础上进行布局, 计算每个节点的几何结构
把每个节点绘制到屏幕上 (painting)
复制代码

加载方式

css 异步加载(不阻塞)
img 异步加载(不阻塞)
js 同步加载(阻塞)
复制代码

放置顺序

css 放置于<head>标签中
原因:要是页面在无CSS渲染下先加载HTML的话将会面目全非,样式先行的话在加载HTML内容时可以同时渲染样式

js 放置于</body>标签之前、body标签中html内容的后面
原因:为了提高页面渲染的速度效率。浏览器在加载<script>元素内部的JS代码将被从上至下依次解释,解释器对<script>元素内部所有代码求值完毕之前,会阻塞其他资源的加载,页面的其余内容都不会被浏览器加载显示,如果放置在前面其他位置,会对页面内容的加载速度产生影响。
复制代码

7.回流和重绘

回流必将引起重绘,重绘不一定会引起回流。回流比重绘的代价要更高。

回流:Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。

会导致回流的操作:

  • 页面首次渲染
  • 浏览器窗口大小发生改变
  • 元素尺寸或位置发生改变
  • 元素内容变化(文字数量或图片大小等等)
  • 元素字体大小变化
  • 添加或者删除可见DOM元素
  • **CSS伪类(例如::hover
  • 查询某些属性或调用某些方法

一些常用且会导致回流的属性和方法:

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

重绘: 当页面中元素样式的改变并不影响它在文档流中的位置时(例如:colorbackground-colorvisibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。

三、JavaScript

1.JavaScript基本数据类型

数字(number)、字符串(string)、布尔值(boolean)、undefined、null、对象(Object)、Symbol (ES6)

2.事件冒泡和事件委托

  • 事件冒泡:子级元素的某个事件被触发,它的上级元素的该事件也被递归触发。
  • 事件委托:使用了事件冒泡的原理,从触发某事件的元素开始,递归地向上级元素传播事件。
  • 阻止事件冒泡event.stopPropagation()
  • 阻止默认事件 event.preventDefault()
  • 阻止调用相同事件的其他侦听器 event.stopImmediatePropagation
  • 事件委托给父元素后,如何得知事件是哪个子元素触发的? 答:可以通过event.target对象来获取

3.原型链/原型继承

JavaScript中每个对象都有一个私有属性(称之为 __proto__),它指向它的原型对象(prototype)。该 prototype 对象又具有一个自己的 __proto__ ,层层向上直到一个对象的原型为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

4.闭包

闭包就是能够读取其他函数内部变量的函数。在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成**“定义在一个函数内部的函数“ **。在本质上,闭包是将函数内部和函数外部连接起来的桥梁

function fn () {
  var n = 1
  return function bar () {
    console.log(n++)
  }
}
复制代码

5.怎么把一个类数组对象转化为数组

  • var arr = Array.prototype.slice.call(arguments); 等同于var arr = [].slice.call(arguments)
  • ES6新方法var arr = Array.from(arguments);
  • Jquery方法 var arr = $.makeArray(arguments);

6.ES6新特性

let 、const、 => 、 import、 export、 export defualt

7.ES7新特性

includes、**表示乘方

8.ES8新特性

`padStart、padEnd、Object.values(obj)返回对应的value数组、Object.entries(obj)返回的是有每一对键值对数组组成的数组、Object.getOwnPropertyDescriptors(obj)获取属性信息

9.Array数组的方法有哪些

toString()、valueOf()、toLocaleString()、join()、push()、pop()、shift()、unshift()、reverse()、sort()、concat()、slice()、indexOf()、lastIndexOf()、reduce()、map()、forEach()、filter() Array方法详细介绍

10.String有哪些方法

concat()、charAt()、slice()、substr()、substring()、split()、trim()、toLowerCase()、toUpperCase()、match()、search() String方法详细介绍

11.实现函数能够深度克隆任何类型

1. JSON.parse方法
const newObj = JSON.parse(JSON.stringify(oldObj));
2. 构造一个深克隆函数
function deepClone (obj) {
  if (typeof obj !== "object" && typeof obj !== "function") {
    return obj;
  }
  if (typeof obj === "function") {
    return eval(obj.toString());   // 有问题
  }
  if (obj.constructor === Date) {
    return new Date(obj.getTime());
  }
  if (obj.constructor === RegExp) {
    return new RegExp(obj);
  }
  var o = Array.isArray(obj) ? [] : {};
  for (i in obj) {
    if (obj.hasOwnProperty(i)) {
      o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
    }
  }
  return o;
}
复制代码

12.==和===的区别

==用于比较判断两者相等 ==在比较的时候可以转自动换数据类型

===用严格比较判断两者严格相等===严格比较,不会进行自动转换

13.var 和let的区别

  • var函数作用域, let块级作用域
  • var会变量提升, let不会变量提升
  • var可以重复定义, let不可以重复定义

14. 0.1 + 0.2 > 0.3的原因

0.1的二进制格式是:0.0001100011....。这是一个二进制无限循环小数,但计算机内存有限,我们不能用储存所有的小数位数。那么在精度与内存间如何取舍呢?

答案是:在某个精度点直接舍弃。当然,代价就是,0.1在计算机内部根本就不是精确的0.1,而是一个有舍入误差的0.1。当代码被编译或解释后,0.1已经被四舍五入成一个与之很接近的计算机内部数字,以至于计算还没开始,一个很小的舍入错误就已经产生了。这也就是 0.1 + 0.2 不等于0.3 的原因。

14. MVP、MVC、MVVM

MVC

 

前端面试整理

 

 

MVP

 

前端面试整理

 

 

MVVM

 

前端面试整理

 

 

Controller: 负责监听View的用户事件,得到数据后Controller做一些处理,然后渲染View。
Presenter: 比起Controller,Presenter会调用View层提供的接口去渲染Model。这样做有几点好处:面向接口编程、更好的解耦、方便做单元测试
ViewModel: 比起MVP中View需要自己提供API,MVVM在VM中构建一组状态数据(state data),作为View状态的抽象。然后通过双向数据绑定(data binding)使VM中的状态数据(state data)与View中的显示状态(screen state)保持一致。这样,VM中的展示逻辑只需要修改对应的状态数据,就可以控制View的状态,从而避免在View上开发大量的接口。
复制代码

15. 性能优化

a) 减少HTTP请求

b) 使用精灵图和CSS Sprites(CSS精灵)

c) 使用CDN

d) 将样式表放在头部,将脚本放在底部

e) 使用缓存

f) 资源合并压缩

g) 减少DNS查找

h) 使用懒加载、预加载

16. setTimeout 和setInterval的区别

setTimeout(表达式,延时时间)在执行时,是在载入后延迟指定时间后,去执行一次表达式,记住,次数是一次 而setInterval(表达式,交互时间),它从载入后,每隔指定的时间就执行一次表达式 ,直到 clearInterval() 被调用或窗口被关闭

17.setTimeout时间设为0是否立即执行,为什么

JavaScript 是单线程执行的,也就是无法同时执行多段代码, 如果代码中设定了一个 setTimeout,那么浏览器便会在合适的时间,将代码插入任务队列,如果这个时间设为 0,就代表立即插入队列,但不是立即执行。

18. 函数字面量和函数声明的区别

声明函数具有函数提升效果,可以在声明函数的代码前执行函数

console.log(add2(1,1)); //输出2
function add2(a,b){    //函数声明
    return a+b;
}
console.log(add1(1,1));  //报错:add1 is not a function
var add1 = function(a,b){
    return a+b;
}
复制代码

19.let暂时性死区(TDZ)的原因

var会变量提升(预解析),let不会变量提升(变量提升:函数及变量的声明都将被提升到函数的最顶部。 )

if(true){
   // TDZ开始
   tmp = 'abc'  //报错
   let tmp; //TDZ结束
}
复制代码

20.闭包与函数作用域的联系

函数作用域是产生闭包的原因

21. 数组不变性

  • 通过push, unshift, shift, pop方法改变数组长度, 都会导致原数组改变, 这不符合函数编程中的不变性质
  • 使用concat将返回一个新的数组, 原数组不改变
  • 使用splice会改变原数组
  • slice截取数组中的部分items,返回新的数组, 不改变原数组

22.函数参数arguments

在Javascript函数体内,标识符arguments具有特殊含义。它是调用对象的一个特殊属性,用来引用Arguments对象。 Arugments对象就像数组 ,其中arguments[0]表示第一个参数。 arguments.length长度

23.XXS和CSRF

XSS定义的主语是“脚本”,是一种跨站执行的脚本,也就是javascript脚本,指的是在网站上注入我们的javascript脚本,执行非法操作。

CSRF定义的主语是”请求“,是一种跨站的伪造的请求,指的是跨站伪造用户的请求,模拟用户的操作。

XSS: 通过客户端脚本语言(最常见如:JavaScript) 在一个论坛发帖中发布一段恶意的JavaScript代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS!

CSRF:又称XSRF,冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求(如恶意发帖,删帖,改密码,发邮件等)。

防御XSS攻击可以通过以下两方面操作:

  • 对用户表单输入的数据进行过滤,对javascript代码进行转义,然后再存入数据库;
  • 在信息的展示页面,也要进行转义,防止javascript在页面上执行。

CSRF攻击的防御可以通过以下两方面操作:

  • 验证 HTTP Referer 字段
  • 在请求地址中添加 token 并验证
  • 在 HTTP 头中自定义属性并验证

24.typeof返回的类型

"number","string","boolean","object","function","undefined"
复制代码

25.new操作符具体干了什么

new共经历了四个过程。

var fn = function () { };
var fnObj = new fn();
复制代码

创建一个空对象

var obj = new object()
复制代码

设置原型链

obj._proto = fn.prototype;
复制代码

让fn的this指向obj,并执行fn函数体

var result = fn.call(obj);
复制代码

判断fn的返回值类型,如果是值类型,返回obj。如果是引用类型,就返回这个引用类型的对象。

if (typeof(result) == "object"){  
    fnObj = result;  
} else {  
    fnObj = obj;
}
return fnObj
复制代码

26.怎么判断是不是数组

var arr = new Array("123", "ash")

- arr instanceof Array
- Array.isArray(arr)
- arr.constructor   //查看输出是否为function Array(){ [native code] }
- Object.prototype.toString.call(arr) === '[object Array]'
复制代码

27. __proto__prototype的区别

__proto__(隐式原型)与prototype(显式原型) ,__proto__指向prototype

28. this绑定

默认绑定:

a) 全局环境中,this默认绑定到window console.log(this === window);//true

b) 函数独立调用时,this默认绑定到window

function foo(){
    console.log(this === window);
}
foo(); //true
复制代码

c) 被嵌套的函数独立调用时,this默认绑定到window

//虽然test()函数被嵌套在obj.foo()函数中,但test()函数是独立调用,而不是方法调用。所以this默认绑定到window
var a = 0;
var obj = {
  a: 2,
  foo: function () {
    function test () {
      console.log(this.a);
    }
    test();
  }
}
obj.foo(); // 0
复制代码

隐式绑定

a) 一般地,被直接对象所包含的函数调用时,也称为方法调用,this隐式绑定到该直接对象

function foo () {
  console.log(this.a);
};
var obj1 = {
  a: 1,
  foo: foo,
  obj2: {
    a: 2,
    foo: foo
  }
}

//foo()函数的直接对象是obj1,this隐式绑定到obj1
obj1.foo(); // 1

//foo()函数的直接对象是obj2,this隐式绑定到obj2
obj1.obj2.foo();// 2
复制代码

隐式丢失

a) 隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到window。这种情况容易出错却又常见

var a = 0;
function foo(){
    console.log(this.a);
};
var obj = {
    a : 2,
    foo:foo
}
//把obj.foo赋予别名bar,造成了隐式丢失,因为只是把foo()函数赋给了bar,而bar与obj对象则毫无关系
var bar = obj.foo;
bar(); // 0
复制代码

显式绑定

a) 通过call()、apply()、bind()方法把对象绑定到this上,叫做显式绑定。对于被调用的函数来说,叫做间接调用

var a = 0;
function foo(){
    console.log(this.a);
}
var obj = {
    a:2
};
foo(); // 0
foo.call(obj); // 2
复制代码

new绑定

如果函数或者方法调用之前带有关键字new,它就构成构造函数调用。对于this绑定来说,称为new绑定

function fn(){
    this.a = 2;
}
var test = new fn();
console.log(test); // {a:2}
复制代码

29.JS继承

a) 原型链继承

核心: 将父类的实例作为子类的原型

function Cat(){ 
}
Cat.prototype = new Animal(); //父类Animal实例
Cat.prototype.name = 'cat';
Cat.prototype.constructor = Cat;

//&emsp;Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true 
console.log(cat instanceof Cat); //true
复制代码

b) 构造继承

核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
复制代码

c) 实例继承

核心:为父类实例添加新特性,作为子类实例返回

function Cat(name){
  var instance = new Animal();
  instance.name = name || 'Tom';
  return instance;
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false
复制代码

d) 拷贝继承(支持多继承)

function Cat(name){
  var animal = new Animal();
  for(var p in animal){
    Cat.prototype[p] = animal[p];
  }
  Cat.prototype.name = name || 'Tom';
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
复制代码

e) 组合继承

核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
Cat.prototype = new Animal();

// 组合继承也是需要修复构造函数指向的。

Cat.prototype.constructor = Cat;

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
复制代码

f)寄生组合继承

核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
(function(){
  // 创建一个没有实例方法的类
  var Super = function(){};
  Super.prototype = Animal.prototype;
  //将实例作为子类的原型
  Cat.prototype = new Super();
})();

Cat.prototype.constructor = Cat; // 需要修复下构造函数

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true
复制代码

30.通过JS和JQuery获取的元素有什么不同

JS获取的是DOM元素。 jQuery返回的是jQuery对象, jQuery对象比js对象多了一些包装方法,比如.htm() .attr() .css() 等等

31.从输入URL到页面加载发生了什么

  1. DNS解析
    • 在host文件中查找:如果在缓存中都查找不到的情况下,就会读取系统中预设的host文件中的设置。
    • 路由器缓存:有些路由器也有DNS缓存的功能,访问过的域名会存在路由器上。
    • ISP DNS缓存:互联网服务提供商(如中国电信)也会提供DNS服务,比如比较著名的 114.114.114.114,在本地查找不到的情况下,就会向ISP进行查询,ISP会在当前服务器的缓存内查找是否有记录,如果有,则返回这个IP,若没有,则会开始向根域名服务器请求查询。
    • *DNS服务器/根DNS服务器:根域名收到请求后,会判别这个域名(.com)是授权给哪台服务器管理,并返回这个*DNS服务器的IP。请求者收到这台*DNS的服务器IP后,会向该服务器发起查询,如果该服务器无法解析,该服务器就会返回下一级的DNS服务器IP(nicefilm.com),本机继续查找,直到服务器找到(www.nicefilm.com)的主机。
  2. TCP连接(三次握手)
    • 第一次,本机将标识位 SYN 置为 1, seq = x(Sequence number)发送给服务端。此时本机状态为SYN-SENT
    • 第二次,服务器收到包之后,将状态切换为SYN-RECEIVED,并将标识位 SYN 和 ACK都置为1, seq = y, ack = x + 1, 并发送给客户端。
    • 第三次,客户端收到包后,将状态切换为ESTABLISHED,并将标识位ACK置为1,seq = x + 1, ack = y + 1, 并发送给服务端。服务端收到包之后,也将状态切换为ESTABLISHED
  3. 发送HTTP请求
  4. 服务器处理请求并返回HTTP报文
  5. 浏览器解析渲染页面
    • 通过HTML解析器解析HTML文档,构建一个DOM Tree,同时通过CSS解析器解析HTML中存在的CSS,构建Style Rules,两者结合形成一个Attachment。
    • 通过Attachment构造出一个呈现树(Render Tree)
    • Render Tree构建完毕,进入到布局阶段(layout/reflow),将会为每个阶段分配一个应出现在屏幕上的确切坐标。
    • 最后将全部的节点遍历绘制出来后,一个页面就展现出来了。
  6. 连接结束(四次挥手)
    1. 客户端发送一个FIN置为1的包,ack = y, seq = x + 1,此时客户端的状态为 FIN_WAIT_1
    2. 服务端收到包后,状态切换为CLOSE_WAIT发送一个ACK为1的包, ack = x + 2。客户端收到包之后状态切换为FNI_WAIT_2
    3. 服务端处理完任务后,向客户端发送一个 FIN包,seq = y; 同时将自己的状态置为LAST_ACK
    4. 客户端收到包后状态切换为TIME_WAIT,并向服务端发送ACK包,ack = y + 1,等待2MSL后关闭连接。

32.创建对象的方法

通过Object创建对象

var person = new Object();
person.name = "hebiwen";
person.getName = function() {
    console.log(this.name);
};

复制代码

通过字面量创建

var person = {
    name: "hebiwen",
    getName: function() {
        console.log(this.name);
    }
}
复制代码

工场模式(无法识别对象类型,即无法通过instanceofconstructor来识别对象类型)

function createPerson(name) {
    var o = new Object();
    o.name = name;
    o.getNmae = function() {
        console.log(this.name);
    };
    return o;
}
var person = createPerson("hebiwen");
复制代码

构造函数

function Person(name) {
    this.name = name;
    this.getName = function() {
        console.log(this.name);
    }
}
var person  = new Person("person");
复制代码

构造函数的问题:

每个方法都要在每个实例上重新创建一次,尤其是函数,这样每个Person的实例都包含了一个不同的sayName的函数实例。

注意1 构造函数没有return语句。要创建Person的新实例,必须采用new操作符,new操作符大体上完成了一下4件事情:

  • 创建一个新的对象(本例中Person创建的新对象,记为person);
  • 将构造函数的作用域赋给新对象(this=>person);
  • 执行构造函数中的代码(Person中的this.name=name;this.say.....);
  • 返回新对象

注意2 构造函数也是函数,如果不通过new操作符调用,则作用环境为全局(浏览器中为windows,node环境中为global

原型模式

function Person() {}
Person.prototype.name = "hebiwen";
Person.prototype.getName = function() {
    console.log(this.name);
}
var person = new Person();
复制代码

浏览器支持:IE9+,这样所有的Person实例共享name属性及sayName函数

注意1

  • 对象的某个属性是否来自实例,可通过hasOwnProperty()来确定,如果是在原型中,则返回false
  • 判断对象是否具备属性,可以通过in操作符,例如console.log("name" in person)//true来判断,不论是在原型还是实例中,都返回true,通过for-in循环时,实例及原型中均会被枚举。

注意2 在定义原型时,如果用字面量代替为prototype属性定义,则原型的constructor属性不会指向Person。因为通过字面量定义,完全重写了默认的prototype对象。但是此时instanceof还是能够返回正确的结果。

function Person(){};
Person.prototype={
    name : "hebiwen",
    sayName : function(){
        console.log(this.name);
    }
};
var person = new Person();
console.log(person instanceof Person);//true
console.log(person.constructor == Person);//false
console.log(person.constructor == Object);//true
复制代码

注意3 在重定义原型前,不能创建对象实例,否则会造成实例的原型指向错误

构造函数与原型组合

function Person(name) {
    this.name = name;
    this.friends = ["Bob","Harry"];//引用类型为实例属性
}
Person.prototype.getName = function() {
 	console.log(this.name);   
}
复制代码

动态原型

function Person(name) {
    this.name = name;
	this.friends = ["Bob","Harry"];//引用类型为实例属性
	if(typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
            console.log(this.name);
        };
    }
}
复制代码

寄生构造模式

function Person(name) {
    var o = new Object();
    o.name = name;
    o.getName = function() {
        console.log(this.name);
    }
    return o;
}
var person = new Person("hebiwen");
复制代码

稳妥构造函数模式

function Person(name) {
    var o = new Object();
    var _name = name;
    o.getName = function() {
        console.log(_name);
    }
    return o;
}
var person = Person("hebiwen");
复制代码

33.跨域有什么处理方法?(协议、域名、端口 )

  • JSONP

    利用script标签支持跨域的属性,用script标签拿到包裹了数据的方法(相当于是返回了一段js代码),在请求中包含callback,服务端注入参数后返回这个回调函数,然后script标签拿到返回的js代码跨域直接运行回调,需要前后端的配合。
    复制代码
  • CORS

    请求头中的Content-Type请求头的值是下列之一:
    
    - application/x-www-form-urlencoded
    - multipart/form-data
    - text/plain
    复制代码
  • 服务端代理

    因为服务器间的数据交互没有跨域限制,所以我们可以通过一个中间代理服务器来请求目标服务器的数据,也就是开发服务器发送请求到代理服务器,代理服务器再请求目标服务器,将数据返回给开发服务器
    复制代码

34.JSONP支持post请求吗

不支持,因为script不支持post请求

35.参考 jsonp,还有那些发送跨域请求的途径?

img link iframe 等元素都可以发送跨域请求

36.React生命周期

Mounting:组件挂载,已插入真实DOM

  • componentWillMount

组件即将被渲染到页面之前触发,此时可以进行开启定时器、向服务器发送请求等操作

  • render()

组件渲染

  • componentDidMount()

组件已经被渲染到页面中后触发:此时页面中有了真正的DOM的元素,可以进行DOM相关的操作

Updating:组件更新,正在被重新渲染

  • componentWillReceiveProps()

在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。

  • shouldComponentUpdate()

返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。 可以在你确认不需要更新组件时使用。

  • componentWillUpdate()

在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用

  • componentDidUpdate()

在组件完成更新后立即调用。在初始化时不会被调用。

Unmounting:组件移除,已移出真实DOM

  • componentWillUnmount()

组件被销毁时触发。这里我们可以进行一些清理操作,例如清理定时器,取消Redux的订阅事件等等。

 

前端面试整理

 

 

37.Vue生命周期

 

前端面试整理

 

 

 

前端面试整理

 

 

38. Vue数据双向绑定原理

数据劫持: vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的settergetter,在数据变动时发布消息给订阅者,触发相应的监听回调。 Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

发布者-订阅者模式: 一般通过sub, pub的方式实现数据和视图的绑定监听,更新数据方式通常做法是 vm.set('property', value)

 

前端面试整理

 

 

  • 实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
  • 实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
  • 实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

39.实现双向数据绑定

<div>
  <input type="text" id="text1" />
  <span id="text2"></span>
</div>

<script>
  //视图控制器
  var obj = {}
  Object.defineProperty(obj, 'text', {
    set: function(newValue) {
      document.getElementById('text1').value = newValue
      document.getElementById('text2').innerHTML = newValue
    }
  })

  document.addEventListener('keyup', function(e) {
    obj.text = e.target.value
  })
</script>
复制代码

四、网络知识

1.GET和POST的区别

  • GET在浏览器回退时是无害的,而POST会再次提交请求。
  • GET请求只能进行url编码,而POST支持多种编码方式。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制的,而POST没有。
  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • GET参数通过URL传递,POST放在Request body中。
  • GET产生一个TCP数据包(200);POST产生两个TCP数据包 (200 ok)

2.三次握手和四次挥手

 

前端面试整理

 

 

问题1: 为什么要三次握手?

答:三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收机能正常。

问题2:为什么要发送特定的数据包,随便发不行吗?

答:三次握手的另外一个目的就是确认双方都支持TCP,告知对方用TCP传输。

问题3:上图中的SYN和ACK是什么?

答:SYN是标志位,SYN=1表示请求连接;

 

前端面试整理

 

 

问题1: 为什么要四次挥手?

答:根本原因是,一方发送FIN只表示自己发完了所有要发的数据,但还允许对方继续把没发完的数据发过来。

问题2:为什么双方要发送这样的数据包?

答:和握手的情况类似,只是为了让对方知晓自己理解了对方的意图。

3. TCP与UDP基本区别

  • TCP面向连接,UDP是无连接 的
  • TCP要求系统资源较多,UDP较少
  • UDP程序结构较简单
  • 流模式(TCP)与数据报模式(UDP);
  • TCP保证数据正确性,UDP可能丢包
  • TCP保证数据顺序,UDP不保证

4. HTTP缓存

浏览器缓存的优点有:

1.减少了冗余的数据传输,节省了网费

2.减少了服务器的负担,大大提升了网站的性能

3.加快了客户端加载网页的速度

1.强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的network选项中可以看到该请求返回200的状态码;

2.协商缓存:向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源;

**已存在缓存数据时,仅基于强制缓存,请求数据的流程如下 **

 

前端面试整理

 

 

已存在缓存数据时,仅基于对比缓存,请求数据的流程如下

 

前端面试整理

 

 

5.HTTP2

HTTP2.0的新特性

  • 新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
  • 多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
  • header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
  • 服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。目前,有大多数网站已经启用HTTP2.0,例如YouTuBe淘宝网等网站,利用chrome控制台可以查看是否启用HTTP2。

6. CDN原理

CDN工作原理

  1. 用户向浏览器提供要访问的域名;
  2. 浏览器调用域名解析库对域名进行解析,由于CDN对域名解析过程进行了调整,所以解析函数库得到的是该域名对应的CNAME记录(由于现在已经是使用了CDN服务,CNAME为CDN服务商域名),为了得到实际IP地址,浏览器需要再次对获得的CNAME域名进行解析以得到实际的IP地址;在此过程中,使用的全局负载均衡DNS解析(全局负载均衡主要用于在多个区域拥有自己服务器的站点,为了使全球用户只以一个IP地址或域名就能访问到离自己最近的服务器,从而获得最快的访问速度。),如根据地理位置信息解析对应的IP地址,使得用户能就近访问。(CDN服务来提供最近的机器)
  3. 此次解析得到CDN缓存服务器的IP地址,浏览器在得到实际的IP地址以后,向缓存服务器发出访问请求;
  4. 缓存服务器根据浏览器提供的要访问的域名,通过Cache内部专用DNS解析得到此域名的实际IP地址,再由缓存服务器向此实际IP地址提交访问请求;
  5. 缓存服务器从实际IP地址得得到内容以后,一方面在本地进行保存,以备以后使用,二方面把获取的数据返回给客户端,完成数据服务过程;
  6. 客户端得到由缓存服务器返回的数据以后显示出来并完成整个浏览的数据请求过程。

7. HTTPS加密过程

  1. 首先,客户端 A 访问服务器 B ,比如我们用浏览器打开一个网页 www.baidu.com ,这时,浏览器就是客户端 A ,百度的服务器就是服务器 B 了。这时候客户端 A 会生成一个随机数1,把随机数1 、自己支持的 SSL 版本号以及加密算法等这些信息告诉服务器 B 。
  2. 服务器 B 知道这些信息后,然后确认一下双方的加密算法,然后服务端也生成一个随机数 B ,并将随机数 B 和 CA 颁发给自己的证书一同返回给客户端 A 。
  3. 客户端 A 得到 CA 证书后,会去校验该 CA 证书的有效性,校验方法在上面已经说过了。校验通过后,客户端生成一个随机数3 ,然后用证书中的公钥加密随机数3 并传输给服务端 B 。
  4. 服务端 B 得到加密后的随机数3,然后利用私钥进行解密,得到真正的随机数3。
  5. 最后,客户端 A 和服务端 B 都有随机数1、随机数2、随机数3,然后双方利用这三个随机数生成一个对话**。之后传输内容就是利用对话**来进行加解密了。这时就是利用了对称加密,一般用的都是 AES 算法。
  6. 客户端 A 通知服务端 B ,指明后面的通讯用对话**来完成,同时通知服务器 B 客户端 A 的握手过程结束。
  7. 服务端 B 通知客户端 A,指明后面的通讯用对话**来完成,同时通知客户端 A 服务器 B 的握手过程结束。
  8. SSL 的握手部分结束,SSL 安全通道的数据通讯开始,客户端 A 和服务器 B 开始使用相同的对话**进行数据通讯。

8. http常用请求方式

序号 方法 描述
1 GET 请求指定的页面信息,并返回实体主体。
2 HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
3 POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
4 PUT 从客户端向服务器传送的数据取代指定的文档的内容。
5 DELETE 请求服务器删除指定的页面。
6 CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
7 OPTIONS 允许客户端查看服务器的性能。
8 TRACE 回显服务器收到的请求,主要用于测试或诊断。

9. cookie、session、localStorage、sessionStorage的区别

cookie和session的区别(cookie和session都是用来跟踪浏览器用户身份的会话方式。 )

a) 保持状态 :cookie保存在浏览器端,session保存在服务器端

b) 存储内容:cookie只能保存字符串类型,以文本的方式;session通过类似与Hashtable的数据结构来保存,能支持任何类型的对象(session中可含有多个对象)

c) 存储的大小:cookie:单个cookie保存的数据不能超过4kb;session大小没有限制。

d) 安全性:cookie:针对cookie所存在的攻击:Cookie欺骗,Cookie截获;session的安全性大于cookie。

WebStorage

HTML5的WebStorage提供了两种API:localStorage(本地存储)和sessionStorage(会话存储)

a) 生命周期:localStorage:localStorage的生命周期是永久的,关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。

b) 存储大小:localStorage和sessionStorage的存储数据大小一般都是:5MB

c) 存储位置:localStorage和sessionStorage都保存在客户端,不与服务器进行交互通信。

d) 存储内容类型:localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理

e) 应用场景:localStoragese:常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据。sessionStorage:敏感账号一次性登录;

10. WebSocket

最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息 ,HTTP 协议做不到服务器主动向客户端推送信息。

(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

11.域名收敛和域名发散

  • 域名收敛:就是将静态资源放在一个域名下。减少DNS解析的开销。
  • 域名发散:是将静态资源放在多个子域名下,就可以多线程下载,提高并行度,使客户端加载静态资源更加迅速。

五、其它

1.git 一个分支已经提交了,你现在的代码已经写了很多,发现之前有个BUG要改,怎么办

先暂存一下工作空间改动:git stash

新建一个分支,并且换到这个新分支

git branch fix_bug//新建分支

git checkout fix_bug//切换分支

这时候就可以安心的在这个fix_bug分支改bug了,改完之后

git add .

git commit -m "fix a bug"

切换到master主分支

git checkout master

从fix_bug合并到master分支

git merge fix_bug

提交代码

git push

然后从暂存区恢复代码

git stash pop

2.数据库事务特性

  1. 原子性(Atomicity)

    原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

  2. 一致性(Consistency)

    一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

  3. 隔离性(Isolation)

    隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

  4. 持久性(Durability)

    持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

3. 数据库隔离级别

  • READ_UNCOMMITTED 读未提交:最低级别,一个事务可以读取另一个未提交事务的数据。幻读、不可重复读和脏读都允许。
  • READ_COMMITTED 读已提交:一个事务要等另一个事务提交后才能读取数据。允许幻读、不可重复读,不允许脏读。
  • REPEATABLE_READ 可重复读:在开始读取数据(事务开启)时,不再允许修改操作。允许幻读,不允许不可重复读和脏读。
  • SERIALIZABLE 可序列化:*别,在该级别下,事务序列化顺序执行。幻读、不可重复读和脏读都不允许。


作者:何必问
链接:https://juejin.im/post/5d9d57d6518825512e51e7b2
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。