Skip to content
sobird edited this page May 27, 2023 · 11 revisions
Table of Contents

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

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

  • 严格模式 又称标准模式,页面以该浏览器支持的最高标准(W3C标准)运行。

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

HTML5没有DTD,因此没有严格模式与混杂模式的区别,HTML5有相对宽松的语法,尽可能大的实现了向后兼容。( HTML5 没有严格和混杂之分)

意义 严格模式与混杂模式存在的意义与其来源密切相关,如果说只存在严格模式,那么许多旧网站必然受到影响,如果只存在混杂模式,那么会回到当时浏览器大战时的混乱,每个浏览器都有自己的解析模式。

你知道多少种Doctype文档类型?

HTML4.01 规定了三种文档类型:Strict、Transitional以及Frameset。 HTML5只有一种文档类型。

Strict

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
Transitional
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " http://www.w3.org/TR/html4/loose.dtd">
Frameset
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" " http://www.w3.org/TR/html4/frameset.dtd">

HTML5

<!DOCTYPE html>

请谈一下HTML和XHTML的区别。

HTML称为超文本标记语言`Hyper Text Markup Language`,是一种标识性的语言。XHTML称为扩展超文本标记语言`Extensible HyperText Markup Language`,同样是一种标识性的语言,表现方式与HTML类似,不过语法上更加严格。从关系上讲,HTML是基于标准通用标记语言`SGML`的应用,XML是SGML的一个子集,而XHTML则基于`XML`。

语言基础

  • XHTML基于可扩展标记语言XML。

  • HTML基于标准通用标记语言SGML。

语法严格程度

  • XHTML 元素必须被关闭,空标签也必须被关闭。

  • XHTML 标签名必须用小写字母。

  • XHTML 文档必须拥有根元素。

  • XHTML 标签顺序必须正确。

  • XHTML 文档要求给所有属性赋一个值,属性值不能简写。

  • XHTML 要求所有的属性必须用引号""括起来。

  • XHTML 文档需要把所有<、>、&等特殊符号用编码表示。

  • XHTML 文档不能在注释内容中使用--。

  • XHTML 图片必须有说明文字。

  • XHTML 文档中用id属性代替name属性。

  • HTML 语法要求比较松散。

混合应用

  • XHTML 可以混合各种XML应用,比如MathML、SVG。

  • HTML4.0 不能混合其它XML应用,但在HTML5中已可以嵌入MathML、SVG等应用。

大小写敏感

  • XHTML 对大小写敏感,标准的XHTML标签应该使用小写。

  • HTML 对大小写不敏感。

公布时间

  • XHTML 是2000年W3C公布发行的。

  • HTML4.01 是1999年W3C推荐标准。

<img>标签上title与alt属性的区别是什么?

alt 属性是图片不能加载时在页面显示的提示信息,它会直接输出在原本加载图片的地方,title 属性是在你鼠标悬停在该图片上时显示一个小提示,鼠标离开就没有了。HTML的绝大多数标签都支持title属性,alt只在<IMG>标签里才有。

行内元素有哪些?块级元素有哪些? 空(void)元素有那些?

CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,比如div默认display属性值为“block”,成为“块级”元素;span默认display属性值为“inline”,是“行内”元素。

  • 行内元素有:a b span img input select strong strong button label select

  • 块级元素有:div section article aside header footer ul ol li dl dt dd h1~h6 p blockquote

  • 知名的空元素:br hr img input link meta

  • 少见的空元素:area base col command embed keygen param source track wbr

常见浏览器兼容性问题?

  • 浏览器默认的margin和padding不同。解决方案是加一个全局的`*{margin:0;padding:0;}`来统一。

  • png24位的图片在iE6浏览器上出现背景,解决方案是做成PNG8。也可以引用一段脚本处理.

  • IE6双边距bug:块属性标签float后,又有横向的margin情况下,在ie6显示margin比设置的大。

  • 浮动ie产生的双倍距离(IE6双边距问题:在IE6下,如果对元素设置了浮动,同时又设置了margin-left或margin-right,margin值会加倍。)`#box{ float:left; width:10px; margin:0 0 0 100px;}`这种情况之下IE会产生20px的距离,解决方案是在float的标签样式控制中加入_display:inline;将其转化为行内属性。(_这个符号只有ie6会识别)渐进识别的方式,从总体中逐渐排除局部。

  • IE下,event对象有x,y属性,但是没有pageX,pageY属性; Firefox下,event对象有pageX,pageY属性,但是没有x,y属性.

  • 事件模型不同,.attachEvent 和 .addEventListener .detachEvent和.removeEventListener,IE事件模型只支持事件冒泡(Bubbling)不支持事件捕获(Capturing)

  • 阻止浏览器默认行为:W3C调用`e.preventDefault(),IE下则`window.event.returnValue=false

  • 阻止事件冒泡:在W3C标准里调用`e.stopPropagation()`,而在IE下通过设置`window.event.cancelBubble=true`来实现。

  • DOMContentLoaded onreadystatechange complete

  • DOMMouseScroll FF onmousewheel 非FF

  • event.wheelDelta 上滚120 下-120 event.detail 上滚-3 下3

  • obj.getCurrentStyle[attr] getComputedStyle(obj,false)[attr]

  • XMLHttpRequest和ActiveXObject('Mircorsoft.XMLHttp')

  • 事件源srcElement||target和toElement||relatedTarget

  • obj.setCapture()只有ie认,obj.releaseCapture();

JavaScript数据类型有哪些

  • 基本类型:String、Number、Boolean、Undefined、Uull、Symbol(ES6)、BigInt(ES6)

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

什么是闭包(Closure)?优缺点?

闭包就是在函数内部定义的函数可访问其外部函数的作用域。

应用闭包场景主要是为了:设计私有的方法和变量。这在做框架的时候体现更明显,有些方法和属性只是运算逻辑过程中的使用的,不想让外部修改这些属性,因此就可以设计一个闭包来只提供方法获取。

闭包的缺点就是常驻内存,会增大内存开销,使用不当很容易造成内存泄露(IE内存泄露问题)。

介绍一下css的盒子模型。

有两种, IE盒子模型、标准W3C盒子模型;IE的content部分包含了border和pading;盒模型包括: 内容(content)、填充(padding)、边界(margin)、边框(border)。

css box model

CSS3 box-sizing 属性用法。

`box-sizing`属性定义如何计算一个元素的总宽度和总高度,主要设置是否需要加上内边距(padding)和边框(border)等。

box-sizing: content-box|border-box|inherit;

  • content-box 默认值。 边框和内边距的宽度会被增加到最后绘制出来的元素宽度中

  • border-box 设置的边框和内边距的值是包含在 width 内的

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

HTML5的sessionStorage和localStorage以及cookie,webstorage和cookie的区别

  • sessionStorage 用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此 sessionStorage 不是一种持久化的本地存储,仅仅是会话级别的存储。

  • localStorage 用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。

  • cookie 数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。

webstorage和cookie的共同点 都是保存在浏览器端,且同源的。

webstorage和cookie的区别 webstorage的概念和cookie相似,区别是它是为了更大容量存储设计的(可达到5M或更大)。Cookie的大小是受限的(不超过4K),并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。

webstorage不会自动把数据发给服务器,仅在本地保存。

除此之外,webstorage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie。

但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在,而webstorage仅仅是为了在本地`存储`数据。

HTTP Request Headers 和 Response Headers 都有哪些值?

Request Headers

  • Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8

  • Accept-Encoding:gzip, deflate, sdch

  • Accept-Language:zh-CN,zh;q=0.8,en;q=0.6

  • Cache-Control:max-age=0

  • Connection:keep-alive

  • Cookie:BIDUPSID=A619DDC165924FE0FA2416B87C081FA9; PSTM=1440083528;

  • Host:sobird.me

  • User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36

Response Header

  • Connection:keep-alive

  • Content-Encoding:gzip

  • Content-Type:text/html; charset=utf-8

  • Date:Tue, 25 Aug 2015 16:20:50 GMT

  • Server:Apache

  • Set-Cookie:PS_REFER=0; expires=Sun, 30-Aug-2015 16:20:50 GMT; path=/

  • tracecode:12502000530982001162082600

  • tracecode:12501992610527773194082600

  • Transfer-Encoding:chunked

  • Vary:Accept-Encoding

http状态码有那些?

  • 100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息

  • 200 OK 正常返回信息

  • 201 Created 请求成功并且服务器创建了新的资源

  • 202 Accepted 服务器已接受请求,但尚未处理

  • 204 No Content 相应报文中包含若干首部和一个状态行,但没有实体的主体部分。

  • 301 Moved Permanently 请求的网页已永久移动到新位置。

  • 302 Found 临时性重定向。

  • 303 See Other 临时性重定向,且总是使用 GET 请求新的 URI。

  • 304 Not Modified 自从上次请求后,请求的网页未修改过。

  • 400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。

  • 401 Unauthorized 请求未授权。

  • 403 Forbidden 禁止访问。

  • 404 Not Found 找不到如何与 URI 相匹配的资源。

  • 500 Internal Server Error 最常见的服务器端错误。

  • 503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)。

请列举三种禁止浏览器缓存的头字段,并写出响应的设置值

  • Cache-Control : no-cache

  • Pragma = no-cache

  • Expires = -1 // 设置为-1或是0是不缓存

CSS选择符有哪些?哪些属性可以继承?优先级算法如何计算?

  • 通配符选择器(*)

  • id选择器(#ID)

  • 类选择器(.className)

  • 标签选择器(div, h1, p)

  • 后代选择器(li a)

  • 子选择器(ul>li)

  • 相邻选择器(h1+p)

  • 属性选择器(a[rel = "external"])

  • 伪类选择器(a:hover,li:nth-child)

可继承属性:font,font-xxx,color,text-indent,line-height,word-spacing,letter-spacing,visibility等; 非继承属性:border,padding,margin,width,height,background等;

优先级就近原则,同权重情况下样式定义最近者为准;载入样式以最后载入的定位为准;

优先级为:!important > id > class > tag !important比内联优先级高,但内联比id要高

CSS中长度单位有哪些

  • px 像素(计算机屏幕上的一个点)

  • % 百分比

  • in 英寸

  • cm 厘米

  • mm 毫米

  • em em是一个相对单位 1em等于当前的字体尺寸,2em等于当前字体尺寸的两倍

  • rem rem相对于根元素

  • pt 磅 1pt等于1/72英寸

  • pc 12点活字 1pc=12pt

  • ex 1个ex是一个字体的x-height x-height通常是字体尺寸的一半

  • vw/vh vw是可视区宽度单位。1vw等于可视区宽度的百分之一。vw单位跟百分比很相似,不同的是vw的值对所有的元素都一样,与他们父元素或父元素的宽度无关。

  • vmin/vmax vmin的值是vw和vh中较小(大)的值

CSS伪类和伪元素有哪些,有何区别?

正确的利用伪元素和伪类能够让我们的html结构更清晰合理,也能在一定程度上减少JavaScript对DOM的操作。

伪类

:link 应用于未被访问过的链接 :hover 应用于鼠标悬停到的元素 :visited 应用于被访问过的链接,与:link互斥 :focus 应用于拥有键盘输入焦点的元素 :first-child 选择某个元素的第一个子元素 :last-child 选择某个元素的最后一个子元素 :nth-child() 选择某个元素的一个或多个特定的子元素 :nth-last-child() 选择某个元素的一个或多个特定的子元素,从这个元素的最后一个子元素开始算 :nth-of-type() 选择指定的元素 :nth-last-of-type() 选择指定的元素,从元素的最后一个开始计算 :first-of-type 选择一个上级元素下的第一个同类子元素 :last-of-type 选择一个上级元素的最后一个同类子元素 :only-child 选择的元素是它的父元素的唯一一个子元素 :only-of-type 选择一个元素是它的上级元素的唯一一个相同类型的子元素 :empty 选择的元素里面没有任何内容 :enabled 选择每个已启动的元素 :disabled 选择每个已禁止的元素 :checked 选择每个被选中的元素

伪元素

:first-letter 选择元素文本的第一个字(母) :first-line 选择元素文本的第一行 :before 在指定元素的内容前面插入内容 :after 在指定元素的内容后面插入内容 :selection 选择指定元素中被用户选中的内容

CSS3有哪些新属性?

  • border-radius 边框圆角

  • border-shadow 边框阴影

  • border-image 边框图像

  • background-size 指定背景图像的大小。语法:background-size: length|percentage|cover|contain;

  • background-origin 内容框相对定位的背景图片。语法:background-origin: padding-box|border-box|content-box;

  • background-clip 指定绘图区的背景.语法:background-clip: border-box|padding-box|content-box;

  • linear-gradient 线性渐变(Linear Gradients)- 向下/向上/向左/向右/对角方向 background: linear-gradient(direction, color-stop1, color-stop2, …​); 径向渐变(Radial Gradients)- 由它们的中心定义 background: radial-gradient(center, shape size, start-color, …​, last-color);

  • text-shadow 应用于阴影文本。语法:text-shadow: h-shadow v-shadow blur color;

  • text-overflow 指定当文本溢出包含它的元素,应该发生什么。语法:text-overflow: clip|ellipsis|string;

  • word-wrap 允许长的内容可以自动换行。语法:word-wrap: normal|break-word;

  • @font-face @font-face{font-family: myFirstFont;src: url(sansation_light.woff);}

  • transform 应用于元素的2D或3D转换。这个属性允许你将元素旋转,缩放,移动,倾斜等

  • transition 设置元素当过渡效果,四个简写属性为 transition-property transition-duration transition-timing-function transition-delay

  • media query @media (min-width:800px) and (max-width:1200px) and (orientation:portrait) { …​ }

  • display: flex 伸缩布局盒模型

  • flex-direction 指定了弹性容器中子元素的排列方式

  • justify-content 设置弹性盒子元素在主轴(横轴)方向上的对齐方式

  • align-items 设置弹性盒子元素在侧轴(纵轴)方向上的对齐方式。

  • align-content 修改flex-wrap属性的行为,类似align-items, 但不是设置子元素对齐,而是设置行对齐

  • flex-wrap 设置弹性盒子的子元素超出父容器时是否换行

  • flex-flow flex-direction 和 flex-wrap 的简写

  • order 设置弹性盒子的子元素排列顺序

  • align-self 在弹性子元素上使用。覆盖容器的 align-items 属性

  • flex 设置弹性盒子的子元素如何分配空间

打开(隐藏)、关闭(显示)一个对象。Style的display以及visibility的参数是什么?

.test {
  display: block;
  display: none;
  visibility: visible;
  visibility: hidden;
}

DIV+CSS 实现三栏布局,要求中间栏自适应

html, body {
  margin: 0;
  height: 100%;
}
.main {
  height: 100%;
  margin: 0 210px;
  background: #ccc;
}
.left, .right {
  width: 200px;
  height: 100%;
  background: #fefefe;
}
.left {
  float: left;
}
.right {
  float:right
}
<body>
  <div class="left"></div>
  <div class="right"></div>
  <div class="main"></div>
</body>

CSS实现自适应正方形

使用CSS3 vw 单位

<style>
  .square {
    width: 50vw;
    height: 50vw;
    background: #ccc;
  }
</style>
<div class="square">hello,viewport</div>
存在的问题:只能相对于 viewport 进行布局,很多时候我们的业务场景并不是想对于窗口大小缩放正方形大小

设置垂直方向的padding撑开容器

元素的padding或margin的百分比值是参照父元素的宽度这一特性来实现,最常用也是最推荐的方式。

<style>
  .square {
    width: 50%;
    padding-top: 50%;
    height: 0;
    background-color: #ccc;
  }
</style>
<div class="square"></div>
这种布局方式,一般会给父元素设置固定宽度,而子元素设置 width 百分比布局,通过 padding 也是基于父元素的宽度前提下,进行百分比适配。

利用伪元素(:after) + margin(padding)-top 撑开容器

<style>
  .square {
    width: 50%;
    overflow: hidden;
    background: #ccc;
  }

  .square:after {
    content: "";
    display: block;
    padding-bottom: 100%;
  }
</style>
<div class="square"></div>
这里和 padding 的使用是类似的,margin 百分比也是相对于父元素的 width ,设置伪元素的 margin-top/padding-bottom: 100% 其实就是撑开容器的 height,让 heigth = width; 解释一下这里为什么需要设置 overflow:hidden; 开启 BFC。这里是因为父子嵌套的元素垂直方向的margin取最大值。

缺点:容器内无法填充内容

CSS中link和@import的区别

link属于HTML标签,而@import是CSS提供的;页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;import只在IE5以上才能识别,而link是HTML标签,无兼容问题;link方式的样式的权重高于@import的权重.

创建一段html并返回这段html的dom节点对象

var html = '<div><span>test</span></div>';
var tmp = document.createElement('div');
tmp.innerHTML = html;

var el = tmp.children[0];

JavaScript中如何判断对象类型

// typeof 判断
typeof {}; // 'object'
typeof []; // 'object'
typeof new Date(); // 'object'
typeof (new RegExp) // 'object'

// instaceof 判断
([]) instanceof Array; // true
({}) instanceof Object; // true
({}) instanceof RegExp; // false
(new Date) instanceof Date; // true

// Object.prototype.toString.call([])
Object.prototype.toString.call({}); // 返回 "[object Object]"
Object.prototype.toString.call([]); // 返回 "[object Array]"
Object.prototype.toString.call(/reg/ig); // 返回 "[object RegExp]"

什么是JSONP?原理是什么?

JSONP是JavaScript中服务调用的一种方式。通过一个<script>标签发起HTTP GET请求,是实现跨域服务调用一种公认手段。由于<script>可以对跨域资源进行请求,于是可以在页面中动态地append一个<script>并添加src且携带一个callback的url参数,待请求完成后自动调用callback函数。

new操作符具体干了什么

  • 创建一个空对象,

  • 继承了构造函数的原型

  • 将构造函数this指向该对象,属性和方法被加入到该对象中

  • 根据构造函数返回类型作判断,返回正确的值

function myNew(func, ...args) {
  let obj = {};
  obj.__proto__ = func.prototype;
  const result = func.apply(obj, args);
  return result instanceof Object ? result : obj;
}

// 测试
function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.say = function () {
  console.log(this.name)
}

let p = myNew(Person, "sobird", 30)
console.log(p) // Person {name: "sobird", age: 30}
p.say() // sobird

如何解决跨域问题

  • JSONP 支持双向通信。只支持GET。缺点是:不支持POST,同时需要目标服务器在服务端支持

  • CORS 一般公司内部后台项目较为常见

  • 服务代理 Nginx代理

  • document.domain+iframe 主域相同

  • window.name 支持跨主域。缺点是:不支持POST

  • window.postMessage 支持双向通信。缺点是:仅限于HTML5

  • iframe 数据直接写在url中,数据大小受限而且数据暴露在外。

  • iframe + location.hash 跨主域,功能强大,兼容性好,支持跨域的js调用,支持双向通信。缺点是:太复杂,会嵌套太多的

  • Flash 优点是支持强大,相对简单。缺点是:依赖flash,需要在服务器更目录放置crossdomain.xml文件。(浏览器已经不支持Flash)

call()和apply()的作用和区别

作用: 动态改变某个类的某个方法的运行环境。(改变this的指向)

区别: call和apply的第二个参数不相同,call是若干个参数的列表,apply是一个数组

手写一个apply方法

Function.prototype.myApply = function(scope, ...args) {
  let obj = scope || window;
  obj.fn = this;
  let result =  obj.fn(args);

  delete obj.fn;
  return result;
}

let person = {
  name: 'sobird'
};

function say(some) {
  return this.name + some;
}

console.log(say.myApply(person, ' hello')); //

['1', '2', '3'].map(parseInt)的结果是什么?

[1, NaN, NaN]

连等赋值

var a = {n:1};
var b = a;
a.x = a = {n:2};
console.log(a.x); // undefined
console.log(b.x); // {n: 2}

解析:

2assign

  1. 的优先级高于 =,赋值操作是从右到左

    • 声明a对象中的x属性,用于赋值,此时b指向a,同时拥有未赋值的x属性

    • 对a对象赋值,此时变量名a改变指向到对象{n:2}

    • 对步骤1中x属性,也即a原指向对象的x属性,也即b指向对象的x属性赋值

相当于:

var a = { n: 1 };
var b = a;
a.x = undefined;
a = { n: 2 }
b.x = a
console.log(a.x); // undefined
console.log(b); // {n: 2}

TCP三次握手/四次挥手的过程

  • SYN synchronous 标志位 SYN=1 表示建立连接

  • ACK acknowledgement 标志位 ACK=1 表示确认号有效

  • FIN finish 标志位 FIN=1 表示断开连接

  • seq Sequence number 序列号 随机生成的32位序列号

  • ack Acknowledge number 确认号

三次握手过程

三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务端总共发送三个数据包。

  • 第一次握手:客户端向服务端发送一个TCP报文(SYN=1,seq=x),发送完毕后,客户端进入 SYN_SEND 状态等待服务端的确认。

  • 第二次握手:服务端收到数据包后,回传一个TCP报文(SYN=1,ACK=1,seq=y,ack=x+1),发送完毕后,服务端进入 SYN_RCVD 状态。

  • 第三次握手:客户端收到服务端的数据包后,回传一个TCP报文(ACK=1,seq=x+1,ack=y+1),服务端接收数据包后,再次检查数据,检查完后,三次握手完成,双方建立连接,此时服务端进入 ESTABLISHED 状态。

tcp3

三次握手每一次握手可以确认的信息:

  • 第一次握手:服务器端只可以知道自己能够接收客户端的消息

  • 第二次握手:客户端知道自己发送的消息可以被服务器端接收到,以及自己可以接收到服务器端的信息

  • 第三次握手:服务器确认客户端接收到了自己的信息

四次挥手过程

四次挥手(Four-way Handshake),是指终止TCP连接时,需要在客户端和服务器之间发送四个数据包。

客户端或服务端均可主动发起挥手动作,在 socket 编程中,任何一方执行 close() 操作均可产生挥手操作。下面以客户端主动发起挥手动作说明四次挥手过程。

  • 第一次挥手:客户端向服务端发送一个TCP报文(FIN=1,seq=x),表示自己已经没有数据可以发送了,但是仍然可以接受数据。发送完毕后客户端进入 FIN_WAIT_1 状态。

  • 第二次挥手:服务端确认客户端的FIN包,发送一个确认包(ACK=1,ack=x+1),表明自己一接受到了客户端关闭连接的请求,但还没有准备好关闭连接。发送完毕后,服务端进入 CLOSE_WAIT 状态,客户端接收到这个包后,进入 FIN_WAIT_2 状态,等待服务端关闭连接。

  • 第三次挥手:服务端准备好关闭连接时,向客户端发送结束连接请求(FIN=1,seq=y),发送完毕后,服务端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK。

  • 第四次挥手:客户端接收到来自服务器端的关闭请求,发送一个确认包(ACK=1,ack=y+1),并进入 TIME_WAIT 状态,等待可能出现的要求重传的 ACK 包。服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。

客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。

tcp3

TCP 为什么需要三次握手而不是两次握手

  • 为了实现可靠数据传输,TCP 协议的通信双方,都必须维护一个序列号,以标识发送出去的数据包中,哪些是已经被对方收到的。三次握手的过程即是通信双方相互告知序列号起始值,并确认对方已经收到了序列号起始值的必经步骤。

  • 如果只是两次握手,至多只有连接发起方的起始序列号能被确认,另一方选择的序列号则得不到确认。

强缓存与协商缓存的命中和管理

  • 浏览器加载资源,首先根据资源内的HTTP Request Headers来判断是否命中强缓存,如果命中强缓存,则直接从浏览器缓存中读取资源,不会发请求到服务器

  • 假如强缓存没有命中,浏览器就会发送一个请求到服务器,通过服务器来判断资源是否命中协商缓存,如果命中协商缓存,这个请求就会返回,但服务器不会返回资源,它会告知浏览器,资源没有改变,直接从浏览器缓存中读取资源

  • 强缓存和协商缓存的共同之处在于,两者都从自己浏览器缓存中去加载资源,但是强缓存不发送请求到服务器,而协商缓存则发送请求到服务器

  • 当强缓存,协商缓存都没有命中,直接从服务器加载资源数据

Ctrl+F5 强制刷新网页时,直接从服务器中加载,跳过强缓存和协商缓存,而按 F5 刷新网页时,则跳过强缓存,但是会检查协商缓存

强缓存:如何判断命中强缓存?以及强缓存的原理

当查看返回Http状态为200,并且chrome开发者工具中的network中size显示from cache,即为命中强缓存

强缓存是利用Http中的两个header来实现的:ExpiresCache-Control ,前者使用的是绝对时间,后者是相对时间

  • Expires:表示资源过期时间的header,由服务器返回,时间格式为GMT,如: Sat,4 Aug 2018 16:32:33 GMT 当浏览器第一次请求资源,服务器再返回资源的同时,在response header中加上Expires header。浏览器接受该资源后,将资源连同所有header一起缓存下来,因此强缓存中的header不是服务器返回的,而是从缓存中读取来的,所以返回的status状态自然为200成功,浏览器第二次请求资源时,则从缓存中寻找这个资源,找到后,将它的Expires跟当前的请求时间比较,如果Expires还没过期,则直接读取这个资源,命中缓存,否则不行

  • Cache-Control:由于Expires使用的是GMT这种绝对时间,因此在客户端和服务器端时间相差较大时,缓存就容易出问题,Cache-Control是相对时间,如:Cache-Control:max-age=315360000 Cache-Control的原理和Expires相似,只是在判断有效期是否过期的时候,会将Cache-Control设定的有效期拿出算得资源过期时间,再将资源过期时间与请求时间进行比较

协商缓存的原理

假如协商缓存命中,请求响应返回的http状态为304并且会显示一个Not Modified的字符串,这就表明,命中了协商缓存。协商缓存利用的 Last-Modified,If-Modified-Since 以及 ETag、If-None-Match 这两对Header来管理的。浏览器首次请求资源时,服务器返回资源同时会返回加有Last-Modified的header的response,Last-Modified表示这个资源最后一次修改的时间,再次请求资源时,浏览器则在请求的header中添加If-Modified-Since,它的值是上一次请求中Last-Modified的值。当服务器收到资源请求时,根据浏览器传过来的If-Modified-Since和服务器上的最后修改时间来判断资源是否有变化,没有则返回304,有则正常返回资源内容。

ETag、If-None-MatchLast-Modified,If-Modified-Since 的原理类似,只是ETag是一个随机的唯一标识,而不是时间,只要资源有变化这个标识就不同

有哪些触屏事件?

touchstart touchmove touchend touchcancel

谈谈this对象的理解

this 是JavaScript的一个关键字,随着函数使用场景不同,this的值也会不同,只有函数执行的时才能确定this指向谁,那就是this最终指向的是调用函数的那个对象。

实现一个clearfix(清除浮动)代码

.clearfix:after {
  content:".";
  display:block;
  height:0;
  visibility:hidden;
  clear:both;
}
.clearfix {
  *zoom:1;
}

var let const 声明变量的区别

  • var 存在变量提升,即变量可以在声明之前使用,值为undefined,可重复声明。

  • let 是用于替代var来声明变量的。不存在 变量提升

  • const 用来声明常量,一旦声明就必须立即初始化 (var let 声明变量后,还可以重新赋值,const不能重新赋值,但对于引用类型的数据,可以在不重新赋值的情况下修改它的值)

变量提升

function foo() {
  console.log(a);
  var a = 1;
}
foo(); // undefined

// 它的实际执行顺序是
function foo() {
  var a;
  console.log(a);
  a = 1;
}
foo();
// 所以a的值为undefined 

// 内层的tmp变量覆盖了外层的tmp变量
var tmp = new Date();

function f() {
  console.log(tmp);
  if (false) {
    var tmp = 'hello world';
  }
}

f(); // undefined

// let const 不存在变量提升
console.log(bar); // 报错ReferenceError
let bar = 2;
var foo = 1;
function foo() {console.log(1)}
console.log(foo);

// 它实际的执行顺序是
var foo;
foo = function(){console.log(1)};
foo = 1; // 所以foo的值为1

块级作用域

let const 声明的变量只在它所在的代码块有效

let a = 1;
console.log(window.a); // undefined

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc

暂时性死区

只要块级作用域内存在let和const,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

// “暂时性死区”也意味着typeof不再是一个百分之百安全的操作。
typeof x; // ReferenceError
let x;

// 下面 x = y 时 y还未被声明,属于“死区”
function bar(x = y, y = 2) {
  return [x, y];
}

bar(); // 报错
Clone this wiki locally