寫(xiě)在開(kāi)頭
跳槽是為了得到更高的薪酬篱昔,或者為了尋找更具發(fā)展空間的公司一種常見(jiàn)的行為瑞妇。我也于今年完成了一次跳槽,自然也有很多的感悟秉沼,作成本文供大家參考桶雀。
本文主要分成兩個(gè)部分,一部分是我自己整理的面試大綱唬复,另外一部分是面試官考察的問(wèn)題矗积。
面試大綱
關(guān)于面試大綱,我認(rèn)為每個(gè)人都是千差萬(wàn)別的敞咧。因?yàn)槊嬖嚬俣际菍?duì)簡(jiǎn)歷所寫(xiě)的項(xiàng)目經(jīng)驗(yàn)進(jìn)行深挖或者對(duì)你所掌握的基本技能進(jìn)行考察棘捣。
我在簡(jiǎn)歷上寫(xiě)的技能點(diǎn)包含了HTML
/CSS
/JavaScript
/ES6
/HTTP協(xié)議
/Vue
/微信小程序
/Node
/Express
/MySQL
/面向?qū)ο?/code>/
設(shè)計(jì)模式
根據(jù)以上,整理出面試大綱
一休建、HTML
<li>標(biāo)簽之間有空格怎么處理乍恐?
原因:行框的排列會(huì)受到中間空白(回車(chē)空格)等的影響评疗,因?yàn)榭崭褚矊儆谧址?這些空白也會(huì)被應(yīng)用樣式,占據(jù)空間禁熏,所以會(huì)有間隔壤巷,把字符大小設(shè)為0或者將<li>標(biāo)簽寫(xiě)在一排邑彪,就沒(méi)有空格了瞧毙。
二、CSS
CSS3新特性
- 支持rgba和透明度
- 支持媒體查詢(xún)
- 支持自定義字體
- 對(duì)長(zhǎng)的不可分割單詞換行
word-wrap:break-word;
- 文字陰影
text-shadow: 5px 5px 5px #ff0000;
- 盒陰影
box-shadow: 10px 10px 5px #888888
- 支持圓角
border-radius: 50%;
- 邊框圖片
border-image: url(border.png) 30 30 round
CSS優(yōu)先級(jí)如何計(jì)算寄症?
- 元素和偽元素:1
- 類(lèi)選擇器宙彪、屬性選擇器或偽類(lèi):10
- id選擇符:100
- 內(nèi)聯(lián)樣式:1000
- !important聲明的樣式優(yōu)先級(jí)最高,如果沖突再進(jìn)行計(jì)算有巧。
- 繼承得到的樣式的優(yōu)先級(jí)最低释漆。
- 如果優(yōu)先級(jí)相同,則選擇最后出現(xiàn)的樣式篮迎。
清除浮動(dòng)的幾種方式和各自的優(yōu)缺點(diǎn)
- 添加空div男图,使用
clear: both;
缺點(diǎn):進(jìn)行清除浮動(dòng);會(huì)添加很多無(wú)意義的空標(biāo)簽甜橱,有違結(jié)構(gòu)與表現(xiàn)的分離逊笆,在后期維護(hù)中將是噩夢(mèng); - 父元素使用
overflow: hidden;
缺點(diǎn):不能配合position
一起使用岂傲,超出的部分會(huì)被隱藏难裆; - 父元素使用
overflow: auto;
缺點(diǎn):超出部分會(huì)出現(xiàn)滾動(dòng)條; - 父級(jí)定義高度
- 推薦使用的方法:父級(jí)div定義偽類(lèi):after和zoom
<style>
.clearfloat {
*zoom: 1;
}
.clearfloat:after {
content: "";
height: 0;
display: block;
clear: both;
visibility: hidden;
}
</style>
<!-- *是為了兼容低版本IE7瀏覽器 zoom是ie屬性镊掖,設(shè)置縮放比例 -->
<div class="box clearfloat">
<div class="left">
<div class="right">
</div>
如何水平居中一個(gè)浮動(dòng)元素乃戈?
#test {
position: absolute;
width: 100px;
height: 100px;
background-color: green;
<!-- 三行代碼缺一不可 -->
margin: 0 auto;
left: 0;
right: 0;
}
<div id="test"></div>
如何水平居中一個(gè)浮動(dòng)元素?
#test {
position: absolute;
width: 100px;
height: 100px;
background-color: green;
<!-- 三行代碼缺一不可 -->
margin: 0 auto;
left: 0;
right: 0;
}
<div id="test"></div>
利用CSS畫(huà)三角形
#triangle {
width: 0;
height: 0;
border-top: 40px solid transparent;
border-left: 40px solid transparent;
border-right: 40px solid transparent;
border-bottom: 40px solid greenyellow;
}
<div id="triangle"><div>
display: none;
和 visibility: hidden;
的區(qū)別亩进?
-
display:none;
不顯示對(duì)應(yīng)的元素症虑,在文檔布局中不再分配空間(回流+重繪) -
visibility:hidden;
隱藏對(duì)應(yīng)元素,在文檔布局中仍保留原來(lái)的空間(重繪)
position
和 float
值相互疊加會(huì)發(fā)生什么归薛?
position:absolute/fixed;
優(yōu)先級(jí)最高侦讨,有他們?cè)跁r(shí),float
不起作用苟翻,display
值需要調(diào)整韵卤。
對(duì)BFC規(guī)范(塊級(jí)格式化上下文:block formatting context)的理解?
BFC規(guī)定了內(nèi)部的Block Box如何布局崇猫。
定位方案:
- 內(nèi)部的Box會(huì)在垂直方向上一個(gè)接一個(gè)放置沈条。
- Box垂直方向的距離由margin決定,屬于同一個(gè)BFC的兩個(gè)相鄰Box的margin會(huì)發(fā)生重疊诅炉。
- 每個(gè)元素的margin box 的左邊蜡歹,與包含塊border box的左邊相接觸屋厘。
- BFC的區(qū)域不會(huì)與float box重疊。
- BFC是頁(yè)面上的一個(gè)隔離的獨(dú)立容器月而,容器里面的子元素不會(huì)影響到外面的元素木缝。
- 計(jì)算BFC的高度時(shí),浮動(dòng)元素也會(huì)參與計(jì)算笼才。
滿足下列條件之一就可觸發(fā)BFC
- 根元素斩松,即html
- float的值不為none(默認(rèn))
- overflow的值不為visible(默認(rèn))
- display的值為inline-block、table-cell憨攒、table-caption
- position的值為absolute或fixed
為什么會(huì)出現(xiàn)浮動(dòng)和什么時(shí)候需要清除浮動(dòng)世杀?清除浮動(dòng)的方式?
浮動(dòng)元素碰到包含它的邊框或者浮動(dòng)元素的邊框停留肝集。由于浮動(dòng)元素不在文檔流中瞻坝,所以文檔流的塊框表現(xiàn)得就像浮動(dòng)框不存在一樣。浮動(dòng)元素會(huì)漂浮在文檔流的塊框上杏瞻。
浮動(dòng)帶來(lái)的問(wèn)題:
- 父元素的高度無(wú)法被撐開(kāi)所刀,影響與父元素同級(jí)的元素
- 與浮動(dòng)元素同級(jí)的非浮動(dòng)元素(內(nèi)聯(lián)元素)會(huì)跟隨其后
- 若非第一個(gè)元素浮動(dòng),則該元素之前的元素也需要浮動(dòng)捞挥,否則會(huì)影響頁(yè)面顯示的結(jié)構(gòu)浮创。
清除浮動(dòng)的方式:
- 父級(jí)div定義height
- 最后一個(gè)浮動(dòng)元素后加空div標(biāo)簽 并添加樣式clear:both。
- 包含浮動(dòng)元素的父標(biāo)簽添加樣式overflow為hidden或auto树肃。
- 父級(jí)div定義zoom
:after
和::after
的區(qū)別是什么蒸矛?
- 在CSS3的規(guī)范里
:
表示偽類(lèi),::
表示偽元素 -
:after
在CSS2.1的規(guī)范中胸嘴,表示偽元素雏掠,隨著WEB的發(fā)展,在CSS3的規(guī)范中劣像,偽元素的語(yǔ)法被修改成使用雙冒號(hào)乡话,成為::after
實(shí)現(xiàn)一個(gè)高度自適應(yīng)的div,里面有兩個(gè)div耳奕,一個(gè)高度100px绑青,希望另一個(gè)填滿剩下的高度
html, body {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
#box {
position: relative;
height: 100%;
width: 200px;
background-color: beige;
}
#box .block-1 {
width: 200px;
height: 100px;
background-color: rosybrown;
}
#box .block-2 {
position: absolute;
top: 100px;
bottom: 0;
width: 200px;
background-color: red;
}
<div id="box">
<div class="block-1"></div>
<div class="block-2"></div>
</div>
三、JavaScript
簡(jiǎn)單說(shuō)說(shuō)繼承的方式和優(yōu)缺點(diǎn)屋群?
原型鏈繼承
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log('parent name:', this.name);
}
function Child(name) {
this.name = name;
}
Child.prototype = new Parent('father');
Child.prototype.constructor = Child;
Child.prototype.sayName = function() {
console.log('child name:', this.name);
}
var child = new Child('son');
child.sayName(); // child name: son
// 這種方法存在兩個(gè)缺陷:
// 1.子類(lèi)型無(wú)法給超類(lèi)型傳遞參數(shù)闸婴,在面向?qū)ο蟮睦^承中,我們總希望通過(guò) var child = new Child('son', 'father'); 讓子類(lèi)去調(diào)用父類(lèi)的構(gòu)造器來(lái)完成繼承芍躏。而不是通過(guò)像這樣 new Parent('father') 去調(diào)用父類(lèi)邪乍。
// 2.Child.prototype.sayName 必須寫(xiě)在 Child.prototype = new Parent('father') 之后,不然就會(huì)被覆蓋掉。
類(lèi)式繼承
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log('parent name:', this.name);
}
Parent.prototype.doSomthing = function() {
console.log('parent do something!');
}
function Child(name, parentName) {
Parent.call(this, parentName);
this.name = name;
}
Child.prototype.sayName = function() {
console.log('child name:', this.name);
}
var child = new Child('son');
child.sayName(); // child name: son
child.doSomthing(); // TypeError: child.doSomthing is not a function
// 解決了原型鏈繼承帶來(lái)的問(wèn)題
// 但存在缺陷:每次創(chuàng)建一個(gè) Child 實(shí)例對(duì)象時(shí)候都需要執(zhí)行一遍 Parent 函數(shù)庇楞,無(wú)法復(fù)用一些公用函數(shù)榜配。
組合式繼承
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log('parent name:', this.name);
}
Parent.prototype.doSomething = function() {
console.log('parent do something!');
}
function Child(name, parentName) {
Parent.call(this, parentName); // 第二次調(diào)用
this.name = name;
}
Child.prototype.sayName = function() {
console.log('child name:', this.name);
}
Child.prototype = new Parent(); // 第一次調(diào)用
Child.prototype.construtor = Child;
var child = new Child('son');
child.sayName();
child.doSomething();
// 第一次調(diào)用構(gòu)造函數(shù)顯然是沒(méi)有必要的,因?yàn)榈谝淮握{(diào)用構(gòu)造函數(shù)時(shí)候不需要函數(shù)內(nèi)部的那些實(shí)例屬性吕晌,這么寫(xiě)只是想獲得其原型上的方法罷了
// 下面的寄生組合式繼承解決了這個(gè)問(wèn)題
寄生組合式繼承
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log('parent name:', this.name);
}
function Child(name, parentName) {
Parent.call(this, parentName);
this.name = name;
}
Child.prototype = Object.create(Parent.prototype); //修改
Child.prototype.construtor = Child;
Child.prototype.sayName = function() {
console.log('child name:', this.name);
}
var parent = new Parent('father');
parent.sayName(); // parent name: father
var child = new Child('son', 'father');
child.sayName(); // child name: son
// tips:
/*
Object.create(proto, [propertiesObject])
Object.create()方法創(chuàng)建一個(gè)新對(duì)象蛋褥,使用現(xiàn)有的對(duì)象來(lái)提供新創(chuàng)建的對(duì)象的__proto__
proto
新創(chuàng)建對(duì)象的原型對(duì)象。
propertiesObject 可選睛驳。
如果沒(méi)有指定為undefined烙心,則是要添加到新創(chuàng)建對(duì)象的可枚舉屬性(即其自身定義的屬性,而不是其原型鏈上的枚舉屬性)對(duì)象的屬性描述符以及相應(yīng)的屬性名稱(chēng)柏靶。這些屬性對(duì)應(yīng)Object.defineProperties()的第二個(gè)參數(shù)弃理。
*/
談?wù)凧S中的this
-
this
是在執(zhí)行上下文創(chuàng)建時(shí)確定的一個(gè)在執(zhí)行過(guò)程中不可更改的變量 -
this
只在函數(shù)調(diào)用階段確定溃论,也就是執(zhí)行上下文創(chuàng)建的階段進(jìn)行賦值屎蜓,保存在變量對(duì)象中。
執(zhí)行上下文钥勋,就是JavaScript引擎在執(zhí)行一段代碼之前將代碼內(nèi)部會(huì)用到的一些
變量
炬转、函數(shù)
、this
提前聲明然后保存在變量對(duì)象中的過(guò)程算灸。
運(yùn)算符優(yōu)先級(jí)
- ()括號(hào) .成員訪問(wèn)
- ()函數(shù)調(diào)用 new
- ++ -- !
- * %
- + -
- >= <= > <
- == !==
- & ^ | 位運(yùn)算符
- && || 邏輯運(yùn)算符
- a ? x : y 條件運(yùn)算符
- = op = 運(yùn)算賦值
// 本題的涉及考點(diǎn)主要還是運(yùn)算符的優(yōu)先級(jí)
function Foo() {
getName = function() {
console.log(1)
}
return this
}
Foo.getName = function() {
console.log(2)
}
Foo.prototype.getName = function() {
console.log(3)
}
var getName = function() {
console.log(4)
}
function getName() {
console.log(5)
}
// 寫(xiě)出以下函數(shù)的執(zhí)行結(jié)果
Foo.getName() // 2
getName() // 4
Foo().getName() // 1
getName() // 1
new Foo.getName() // 2
// new (Foo.getName)()
new Foo().getName() // 3
// (new Foo()).getName()
new new Foo().getName() // 3
// new((new Foo()).getName)()
簡(jiǎn)單聊一聊包裝對(duì)象扼劈?
引用類(lèi)型
和包裝對(duì)象
的區(qū)別在于生存期
引用類(lèi)型所創(chuàng)建的對(duì)象會(huì)一直存在于堆內(nèi)存中,而基本包裝對(duì)象只存在于一瞬間
var str = 'hello';
str.number = 10; //假設(shè)我們想給字符串添加一個(gè)屬性number 菲驴,后臺(tái)會(huì)有如下步驟
/*
var str = new String('hello'); // 1 找到對(duì)應(yīng)的包裝對(duì)象類(lèi)型荐吵,然后通過(guò)包裝對(duì)象創(chuàng)建出一個(gè)和基本類(lèi)型值相同的對(duì)象
str.number = 10; // 2 通過(guò)這個(gè)對(duì)象調(diào)用包裝對(duì)象下的方法 但結(jié)果并沒(méi)有被任何東西保存
str =null; // 3 這個(gè)對(duì)象又被銷(xiāo)毀
*/
alert(str.number); //undefined 當(dāng)執(zhí)行到這一句的時(shí)候,因?yàn)榛绢?lèi)型本來(lái)沒(méi)有屬性赊瞬,后臺(tái)又會(huì)重新重復(fù)上面的步驟
/*
var str = new String('hello'); // 1 找到基本包裝對(duì)象先煎,然后又新開(kāi)辟一個(gè)內(nèi)存,創(chuàng)建一個(gè)值為hello對(duì)象
str.number = undefined // 2 因?yàn)榘b對(duì)象下面沒(méi)有number這個(gè)屬性巧涧,所以又會(huì)重新添加薯蝎,因?yàn)闆](méi)有值,所以值是未定 ;然后彈出結(jié)果
str =null; // 3 這個(gè)對(duì)象又被銷(xiāo)毀
*/
instanceof 和 typeof
instanceof
運(yùn)算符用于測(cè)試構(gòu)造函數(shù)的prototype屬性是否出現(xiàn)在對(duì)象的原型鏈中的任何位置(Instanceof 的使用規(guī)則是: A instanceof B
A沿著proto這條線來(lái)找谤绳,同時(shí)B沿著prototype這條線來(lái)找占锯,如果兩條線能找到同一個(gè)引用,即同一個(gè)對(duì)象缩筛,那么就返回true消略。如果找到終點(diǎn)還未重合,則返回false瞎抛。)
函數(shù)/變量提升
// 1艺演、函數(shù)提升優(yōu)先級(jí)高于變量提升
// 2、表達(dá)式可以修改提升后變量的值
test() // 2
var test = function() {
console.log(1)
}
function test() {
console.log(2)
}
test() // 1
alert(a);
var a=1;
alert(a);
function a(){alert(2)};
alert(a);
var a=3;
alert(a);
function a(){alert(4)};
alert(a);
a();
// function a() {alert (4)};
// 1
// 1
// 3
// 3
// 報(bào)錯(cuò)
new 操作符都干了些什么?
// new共經(jīng)歷了四個(gè)階段
// 1钞艇、創(chuàng)建一個(gè)空對(duì)象
var obj = new Object()
// 2啄寡、設(shè)置原型鏈
obj.__proto__ = Func.prototype
// 3、讓Func中的this指向obj哩照,并執(zhí)行Func的函數(shù)體
var result = Func.call(obj)
// 4挺物、判斷Func的返回值類(lèi)型
// 如果是值類(lèi)型,返回obj飘弧。如果是引用類(lèi)型识藤,就返回這個(gè)引用類(lèi)型的對(duì)象
// (tip: 構(gòu)造函數(shù)默認(rèn) return this,不用寫(xiě))
if(typeof result === 'object') {
return result
} eles {
return obj
}
四次伶、Vue
對(duì)MVVM的理解
MVVM分為Model痴昧、View、ViewModel三者
Model
代表數(shù)據(jù)模型冠王,數(shù)據(jù)和業(yè)務(wù)邏輯都在Model層中定義赶撰;
View
代表UI視圖,負(fù)責(zé)數(shù)據(jù)的展示柱彻;
ViewModel
負(fù)責(zé)監(jiān)聽(tīng) Model 中數(shù)據(jù)的改變并且控制視圖的更新豪娜,處理用戶(hù)交互操作;
Model 和 View 并無(wú)直接關(guān)聯(lián)哟楷,而是通過(guò) ViewModel 來(lái)進(jìn)行聯(lián)系的瘤载,Model 和 ViewModel 之間有著雙向數(shù)據(jù)綁定的聯(lián)系。因此當(dāng) Model 中的數(shù)據(jù)改變時(shí)會(huì)觸發(fā) View 層的刷新卖擅,View 中由于用戶(hù)交互操作而改變的數(shù)據(jù)也會(huì)在 Model 中同步鸣奔。
這種模式實(shí)現(xiàn)了 Model 和 View 的數(shù)據(jù)自動(dòng)同步,因此開(kāi)發(fā)者只需要專(zhuān)注對(duì)數(shù)據(jù)的維護(hù)操作即可惩阶,而不需要自己操作 dom
Vue的雙向數(shù)據(jù)綁定是如何實(shí)現(xiàn)的挎狸?
簡(jiǎn)單來(lái)說(shuō)就是使用數(shù)據(jù)劫持
和發(fā)布訂閱的設(shè)計(jì)模式
實(shí)現(xiàn)的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>MVVM雙向數(shù)據(jù)綁定</title>
</head>
<body>
<script>
class Vue {
constructor(options) {
this.options = options
this.$data = options.data
this.$el = document.querySelector(options.el)
this._directives = {};
// 數(shù)據(jù)劫持
this.Observer(this.$data)
// 解析指令
this.Compile(this.$el)
}
Observer(data) {
for(let key in data) {
this._directives[key] = []
let val = data[key]
let _obj = this._directives[key]
Object.defineProperty(this.$data, key, {
get: function() {
return val
},
set: function(newVal) {
if(val !== newVal) {
val = newVal
_obj.forEach((item) => {
item.update()
})
}
}
})
}
}
Compile(el) {
let nodes = el.children
for(let i=0; i<nodes.length; i++) {
let node = nodes[i]
if(node.children.length) {
this.Compile(node)
}
if(node.hasAttribute('v-text')) {
let attrValue = node.getAttribute("v-text");
this._directives[attrValue].push(new Watch(node, this, attrValue, "innerHTML"))
}
if(node.hasAttribute('v-model')) {
let _this = this
let attrValue = node.getAttribute("v-model");
this._directives[attrValue].push(new Watch(node, this, attrValue, "value"))
node.addEventListener('input', (function(){
return function() {
_this.$data[attrValue] = node.value
}
})())
}
}
}
}
class Watch {
constructor(el, vm, exp, attr) {
this.el = el
this.vm = vm
this.exp = exp
this.attr = attr
this.update()
}
update() {
this.el[this.attr] = this.vm.$data[this.exp]
}
}
</script>
<div id="app">
<h1>數(shù)據(jù)雙向綁定</h1>
<div>
<div v-text="myText"></div>
<input type="text" v-model="myText">
</div>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
myText: '今晚吃雞吶,大吉大利琳猫!'
}
});
</script>
</body>
</html>
Vue如何監(jiān)聽(tīng)某個(gè)屬性值的變化
watch: {
'obj.a': {
handler (newName, oldName) {
console.log('obj.a changed')
}
}
}
computed: {
a1 () {
return this.obj.a
}
}
Vue中給data中的對(duì)象屬性添加一個(gè)新的屬性時(shí)會(huì)發(fā)生什么伟叛,如何解決?
數(shù)據(jù)已經(jīng)添加,但是視圖并沒(méi)有刷新脐嫂;
原因在于在Vue實(shí)例創(chuàng)建時(shí)统刮,obj.b
并未聲明,因此就沒(méi)有被Vue轉(zhuǎn)換為響應(yīng)式的屬性账千,自然就不會(huì)觸發(fā)視圖的更新侥蒙,這時(shí)就需要使用Vue的全局api Vue.$set()
addObjB () {
// this.obj.b = 'obj.b'
this.$set(this.obj, 'b', 'obj.b')
console.log(this.obj)
}
Vue組件通訊的方式
- 父子組件通訊:父->子:使用props,子->父:$emit方法傳遞參數(shù)
- 使用eventBus匀奏,就是創(chuàng)建一個(gè)事件中心鞭衩,相當(dāng)于中轉(zhuǎn)站,可以用它來(lái)傳遞事件和接收事件
- Vuex
可以去掘金找這類(lèi)文章看一下,Vue組件的通訊方式達(dá)6種之多
Vue常用的修飾符
.prevent
: 提交事件不再重載頁(yè)面论衍;
.stop
: 阻止單擊事件冒泡瑞佩;
.self
: 當(dāng)事件發(fā)生在該元素本身而不是子元素的時(shí)候會(huì)觸發(fā);
.capture
: 事件偵聽(tīng)坯台,事件發(fā)生的時(shí)候會(huì)調(diào)用炬丸;
$route 和 $router 的區(qū)別
$route 是“路由信息對(duì)象”,包括path蜒蕾,params稠炬,hash,query咪啡,fullPath首启,matched,name等路由信息參數(shù)
$router 是“路由實(shí)例”對(duì)象包括了路由的跳轉(zhuǎn)方法撤摸,鉤子函數(shù)等
Vue的路由實(shí)現(xiàn):hash模式 和 history模式
hash模式: 在瀏覽器中符號(hào)“#”毅桃,#以及#后面的字符稱(chēng)之為hash,用window.location.hash讀瘸盍铩疾嗅;
特點(diǎn):hash雖然在URL中外厂,但不被包括在HTTP請(qǐng)求中冕象;用來(lái)指導(dǎo)瀏覽器動(dòng)作,對(duì)服務(wù)端安全無(wú)用汁蝶,hash不會(huì)重加載頁(yè)面渐扮。
hash 模式下,僅 hash 符號(hào)之前的內(nèi)容會(huì)被包含在請(qǐng)求中掖棉,如 http://www.xxx.com墓律,因此對(duì)于后端來(lái)說(shuō),即使沒(méi)有做到對(duì)路由的全覆蓋幔亥,也不會(huì)返回 404 錯(cuò)誤耻讽。
history模式: history采用HTML5的新特性;且提供了兩個(gè)新方法:pushState()帕棉,replaceState()可以對(duì)瀏覽器歷史記錄棧進(jìn)行修改针肥,以及popState事件的監(jiān)聽(tīng)到狀態(tài)變更。
history 模式下香伴,前端的 URL 必須和實(shí)際向后端發(fā)起請(qǐng)求的 URL 一致慰枕,如 http://www.xxx.com/items/id。后端如果缺少對(duì) /items/id 的路由處理即纲,將返回 404 錯(cuò)誤具帮。Vue-Router 官網(wǎng)里如此描述:“不過(guò)這種模式要玩好,還需要后臺(tái)配置支持……所以呢,你要在服務(wù)端增加一個(gè)覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源蜂厅,則應(yīng)該返回同一個(gè) index.html 頁(yè)面匪凡,這個(gè)頁(yè)面就是你 app 依賴(lài)的頁(yè)面【蛟常”
對(duì)keep-alive的了解锹雏?
keep-alive是Vue內(nèi)置的一個(gè)組件,可以使被包含的組件保留狀態(tài)术奖,或避免重新渲染
在vue 2.1.0 版本之后礁遵,keep-alive新加入了兩個(gè)屬性: include(包含的組件緩存) 與 exclude(排除的組件不緩存,優(yōu)先級(jí)大于include) 采记。
delete和Vue.delete刪除數(shù)組的區(qū)別佣耐?
delete只是被刪除的元素變成了 empty/undefined 其他的元素的鍵值還是不變;
Vue.delete直接刪除了數(shù)組 改變了數(shù)組的鍵值唧龄。
如何優(yōu)化SPA應(yīng)用的首屏加載速度慢的問(wèn)題兼砖?
- 將公用的JS庫(kù)通過(guò)script標(biāo)簽外部引入,減小app.bundel的大小既棺,讓瀏覽器并行下載資源文件讽挟,提高下載速度;
- 在配置 路由時(shí)丸冕,頁(yè)面和組件使用懶加載的方式引入耽梅,進(jìn)一步縮小 app.bundel 的體積,在調(diào)用某個(gè)組件時(shí)再加載對(duì)應(yīng)的js文件胖烛;
- 加一個(gè)首屏 loading 圖眼姐,提升用戶(hù)體驗(yàn);
Vuex是什么佩番?如何使用众旗?哪種場(chǎng)景使用它?
將需要讀取的狀態(tài)集中放在store
中
改變狀態(tài)的方式是提交mutations
趟畏,這是一個(gè)同步的事務(wù)
異步邏輯應(yīng)該封裝在actions
中
state Vuex 使用單一狀態(tài)樹(shù),即每個(gè)應(yīng)用將僅僅包含一個(gè)store 實(shí)例贡歧,但單一狀態(tài)樹(shù)和模塊化并不沖突。存放的數(shù)據(jù)狀態(tài)赋秀,不可以直接修改里面的數(shù)據(jù)利朵。
mutations 定義的方法動(dòng)態(tài)修改Vuex
的store
中的狀態(tài)或數(shù)據(jù)。
getters 類(lèi)似vue
的計(jì)算屬性沃琅,主要用來(lái)過(guò)濾一些數(shù)據(jù)哗咆。
action 可以理解為通過(guò)將mutations
里面處里數(shù)據(jù)的方法變成可異步的處理數(shù)據(jù)的方法,簡(jiǎn)單的說(shuō)就是異步操作數(shù)據(jù)益眉。view層通過(guò)store.dispath
來(lái)分發(fā)action
modules 項(xiàng)目特別復(fù)雜的時(shí)候晌柬,可以讓每一個(gè)模塊擁有自己的state姥份、mutation、action年碘、getters,使得結(jié)構(gòu)非常清晰澈歉,方便管理
Vue等單頁(yè)應(yīng)用的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):Vue的目標(biāo)是通過(guò)盡可能簡(jiǎn)單的API實(shí)現(xiàn)響應(yīng)的數(shù)據(jù)綁定和組合的視圖組件,核心是響應(yīng)式系統(tǒng)屿衅。
缺點(diǎn):不支持低版本瀏覽器埃难,最低僅支持ie9;不利于SEO的優(yōu)化涤久,首頁(yè)加載耗時(shí)相對(duì)偏長(zhǎng)一些涡尘。
四、ES6
let
和var
的區(qū)別
- 不存在變量提升
- 暫時(shí)性的死區(qū)
if (true) {
// --- 死區(qū)開(kāi)始 ---
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp;
// --- 死區(qū)結(jié)束 ---
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
-
let
為JavaScript新增了塊級(jí)作用域
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
// 變量i是var命令聲明的响迂,在全局范圍內(nèi)都有效考抄,所以全局只有一個(gè)變量i,每一次循環(huán)蔗彤,變量i的值都會(huì)發(fā)生改變
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
// 變量i是let聲明的川梅,當(dāng)前的i只在本輪循環(huán)有效,所以每一次循環(huán)的i其實(shí)都是一個(gè)新的變量然遏,所以最后輸出的是6贫途。
解構(gòu)賦值
定義:從數(shù)組或?qū)ο笾刑崛≈担瑢?duì)變量進(jìn)行賦值
- 數(shù)組的解構(gòu)賦值
let [a, b, c] = [1, 2, 3];
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
let [x, , y] = [1, 2, 3];
x // 1
y // 3
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
let [x, y = 10] = [7]
- 對(duì)象的解構(gòu)賦值
(tip: 數(shù)組的解構(gòu)賦值對(duì)順序有要求待侵,而對(duì)象則沒(méi)有要求丢早,變量必須與屬性同名,才能取到正確的值)
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined
var {x, y = 5} = {x: 1};
// 如果變量名與屬性名不一致诫给,必須寫(xiě)成下面這樣香拉。
// foo 是模式, baz 才是變量中狂,特別要注意區(qū)分模式和變量
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
- 嵌套解構(gòu)賦值
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"
// p 是模式,不會(huì)被復(fù)制扑毡,若想被賦值胃榕,可以寫(xiě)成如下形式
let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]
箭頭函數(shù)和非箭頭函數(shù)的區(qū)別
- 箭頭函數(shù)的
this
指向在定義的時(shí)候繼承自外層的第一個(gè)普通函數(shù)的this
,若外層沒(méi)有普通函數(shù)瞄摊,指向的是window
- 不能直接修改箭頭函數(shù)的
this
指向 - 箭頭函數(shù)的this指向全局勋又,使用
arguments
會(huì)報(bào)未聲明的錯(cuò)誤。 - 箭頭函數(shù)的this指向普通函數(shù)時(shí),它的
argumens
繼承于該普通函數(shù) - 使用
new
調(diào)用箭頭函數(shù)會(huì)報(bào)錯(cuò)换帜,因?yàn)榧^函數(shù)沒(méi)有constructor
簡(jiǎn)單講講Promise
Promise的特點(diǎn)
狀態(tài)一旦改變就再也不會(huì)發(fā)生改變了
Promise的缺點(diǎn)
- 無(wú)法取消Promise楔壤,一旦新建它就會(huì)立即執(zhí)行,無(wú)法中途取消惯驼;
- 如果不設(shè)置回調(diào)函數(shù)蹲嚣,Promise內(nèi)部拋出的錯(cuò)誤递瑰,不會(huì)反應(yīng)到外部;
- 當(dāng)處于pending狀態(tài)時(shí)隙畜,無(wú)法得知目前進(jìn)展到哪一個(gè)階段(剛剛開(kāi)始還是即將完成)抖部。
如何創(chuàng)建Promise實(shí)例?
const promise = new Promise(function(resolve, reject) {
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
簡(jiǎn)單講講Promise API
- Promise.resolve();
// 1. 如果傳入的 value 本身就是 Promise 對(duì)象议惰,則該對(duì)象作為 Promise.resolve 方法的返回值返回慎颗。
function fn(resolve){
setTimeout(function(){
resolve(123);
},3000);
}
let p0 = new Promise(fn);
let p1 = Promise.resolve(p0);
// 返回為true,返回的 Promise 即是 入?yún)⒌?Promise 對(duì)象言询。
console.log(p0 === p1);
//2. 如果這個(gè)值是個(gè) thenable(thenable對(duì)象指的是具有then方法的對(duì)象)俯萎,返回的 Promise 對(duì)象會(huì)“跟隨”這個(gè) thenable 的對(duì)象,采用它的最終狀態(tài)(指 resolved/rejected/pending/settled)
let promise = Promise.resolve($.ajax('/test/test.json'));// => promise對(duì)象
promise.then(function(value){
console.log(value);
});
- Promise.reject();
- Promise.race
// 類(lèi)方法运杭,多個(gè) Promise 任務(wù)同時(shí)執(zhí)行讯屈,返回最先執(zhí)行結(jié)束的 Promise
// 任務(wù)的結(jié)果,不管這個(gè) Promise 結(jié)果是成功還是失敗县习。 涮母。
- Promise.all
// 類(lèi)方法,多個(gè) Promise 任務(wù)同時(shí)執(zhí)行躁愿。
// 如果全部成功執(zhí)行叛本,則以數(shù)組的方式返回所有 Promise 任務(wù)的執(zhí)行結(jié)果。
// 如果有一個(gè) Promise 任務(wù) rejected彤钟,則只返回 rejected 任務(wù)的結(jié)果来候。
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return getJSON('/post/' + id + ".json");
});
Promise.all(promises).then(function (posts) {
// ...
}).catch(function(reason){
// ...
});
- Promise.prototype.then()
- Promise.prototype.catch() 該方法可以捕獲到then鏈上發(fā)生的任何一個(gè)錯(cuò)誤
- Promise.prototype.finally() 該方法用于指定不管
Promise
對(duì)象最后狀態(tài)如何,都會(huì)執(zhí)行的操作
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {
// finally方法的回調(diào)函數(shù)不接受任何參數(shù)逸雹,這意味著沒(méi)有辦法知道营搅,
//前面的 Promise 狀態(tài)到底是fulfilled還是rejected。這表明梆砸,
// finally方法里面的操作转质,應(yīng)該是與狀態(tài)無(wú)關(guān)的,不依賴(lài)于 Promise 的執(zhí)行結(jié)果帖世。
});
關(guān)于Promise
休蟹,不同面試官考察的深度因人而異,反正做好手寫(xiě)實(shí)現(xiàn)Promise
的準(zhǔn)備即可
五日矫、微信小程序
簡(jiǎn)述微信小程序原理
- 小程序本質(zhì)就是一個(gè)單頁(yè)應(yīng)用赂弓,所有的頁(yè)面渲染和事件處理,都在一個(gè)頁(yè)面內(nèi)進(jìn)行哪轿,但又可以通過(guò)微信客戶(hù)端調(diào)用原生的各種接口盈魁;
- 功能可分為渲染層
webview
和邏輯層appService
兩個(gè)部分;
webview
用來(lái)展現(xiàn)UI窃诉,appService
有來(lái)處理業(yè)務(wù)邏輯杨耙、數(shù)據(jù)及接口調(diào)用赤套;
兩個(gè)部分在兩個(gè)進(jìn)程中運(yùn)行,通過(guò)系統(tǒng)層JSBridge
實(shí)現(xiàn)通信按脚,實(shí)現(xiàn)UI的渲染于毙、事件的處理等。
為什么微信小程序的DOM API不完整辅搬?
因?yàn)槲⑿判〕绦虻匿秩揪€程和腳本線程是分開(kāi)的唯沮,腳本線程獨(dú)立在 JSCore
中,沒(méi)有一個(gè)完整的瀏覽器對(duì)象堪遂。
簡(jiǎn)單談?wù)刉XS?
WXS(weixin script)介蛉,結(jié)合HTML,構(gòu)建頁(yè)面結(jié)構(gòu)溶褪。
<wxs module="m1">var msg = "hello world"; module.exports.message = msg;</wxs>
<view>{{m1.message}}</view>
為什么setData操作會(huì)很昂貴币旧?
頻繁用戶(hù)交互的效果在小程序上表現(xiàn)是比較卡頓的, 例如頁(yè)面有 2 個(gè)元素 A 和 B猿妈,用戶(hù)在 A 上做 touchmove 手勢(shì)吹菱,要求 B 也跟隨移動(dòng)。一次 touchmove
事件的響應(yīng)過(guò)程為:
a彭则、touchmove 事件從視圖層(Webview)拋到邏輯層(App Service)
b鳍刷、邏輯層(App Service)處理 touchmove 事件,再通過(guò) setData 來(lái)改變 B 的位置
一次 touchmove 的響應(yīng)需要經(jīng)過(guò) 2 次的邏輯層和渲染層的通信以及一次渲染俯抖,通信(JSBridge)的耗時(shí)比較大输瓜。此外 setData 渲染也會(huì)阻塞其它腳本執(zhí)行,導(dǎo)致了整個(gè)用戶(hù)交互的動(dòng)畫(huà)過(guò)程會(huì)有延遲芬萍。
談?wù)勑〕绦虻纳芷诤瘮?shù)
onLoad() 頁(yè)面加載時(shí)觸發(fā)尤揣,只會(huì)調(diào)用一次,可獲取當(dāng)前頁(yè)面路徑中的參數(shù);
onShow() 頁(yè)面顯示/切入前臺(tái)時(shí)觸發(fā)柬祠,一般用來(lái)發(fā)送數(shù)據(jù)請(qǐng)求(或者 set to foreground);
onReady() 頁(yè)面初次渲染完成時(shí)觸發(fā) 只會(huì)調(diào)用一次北戏,代表頁(yè)面已可和視圖層進(jìn)行交互(當(dāng)邏輯層通知渲染層 Send Initial Data,且渲染層 First Render 之后調(diào)用)瓶盛;
onHide() 頁(yè)面隱藏/切入后臺(tái)時(shí)觸發(fā)(set to background)最欠, 如底部tab切換到其他頁(yè)面或小程序切入后臺(tái)等;
onUnload() 頁(yè)面卸載時(shí)觸發(fā)(destroy)惩猫,如redirectTo或navigateBack到其他頁(yè)面時(shí)。
小程序頁(yè)面有哪些傳遞數(shù)據(jù)的方法
- 使用全局變量實(shí)現(xiàn)數(shù)據(jù)傳遞
- 頁(yè)面跳轉(zhuǎn)或重定向時(shí)蚜点,使用url帶參數(shù)傳遞數(shù)據(jù)
- 使用組件模板 template傳遞參數(shù)
- 使用緩存?zhèn)鬟f參數(shù)
- 使用數(shù)據(jù)庫(kù)傳遞數(shù)據(jù)
請(qǐng)談?wù)勎⑿判〕绦蛑饕夸浐臀募淖饔茫?/h5>
- project.config.json 項(xiàng)目配置文件轧房,用得最多的就是配置是否開(kāi)啟https校驗(yàn);
- App.js 設(shè)置一些全局的基礎(chǔ)數(shù)據(jù)等绍绘;
- App.json 底部tab, 標(biāo)題欄, 小程序的window背景色和路由等設(shè)置奶镶;
- App.wxss 公共樣式迟赃,引入iconfont等;
- pages 里面包含一個(gè)個(gè)具體的頁(yè)面厂镇;
- index.json (配置當(dāng)前頁(yè)面標(biāo)題和引入組件等)纤壁;
- index.wxml (頁(yè)面結(jié)構(gòu));
- index.wxss (頁(yè)面樣式表)捺信;
- index.js (頁(yè)面的邏輯酌媒,請(qǐng)求和數(shù)據(jù)處理等);
談?wù)勎⑿判〕绦?wxss樣式
- 新增加了尺寸單位rpx(tip: rpx換算px規(guī)則是屏幕寬度/750, iphone6下迄靠,1rpx = 0.5px)
- 提供了全局樣式(app.wxss)和局部樣式(page.wxss)
- WXSS 僅支持部分 CSS 選擇器( > :first-of-type :nth-child 均不支持)
六秒咨、HTTP協(xié)議
HTTP請(qǐng)求中的內(nèi)容
- 請(qǐng)求行
GET /images/logo.gif HTTP/1.1
- 首部
- 通用首部
- 請(qǐng)求首部
- 響應(yīng)首部
- 實(shí)體首部
- 實(shí)體
HTTP狀態(tài)碼
- 1**: 信息,服務(wù)器收到請(qǐng)求掌挚,需要請(qǐng)求者繼續(xù)執(zhí)行操作
- 2**: 成功雨席,操作被成功接收并處理
- 3**: 重定向,需要進(jìn)一步的操作以完成請(qǐng)求
- 304 Not Modified 所請(qǐng)求的資源未修改吠式,服務(wù)器返回此狀態(tài)碼時(shí)陡厘,不會(huì)返回任何資源。
- 4**: 客戶(hù)端錯(cuò)誤特占,請(qǐng)求包含語(yǔ)法錯(cuò)誤或無(wú)法完成請(qǐng)求
- 400 客戶(hù)端請(qǐng)求的語(yǔ)法錯(cuò)誤糙置,服務(wù)端無(wú)法理解
- 403 Forbidden 服務(wù)器理解請(qǐng)求客戶(hù)端的請(qǐng)求,但是拒絕執(zhí)行此請(qǐng)求
- 404 Not Found 服務(wù)器無(wú)法根據(jù)客戶(hù)端的請(qǐng)求找到資源(網(wǎng)頁(yè))
- 5**: 服務(wù)器錯(cuò)誤摩钙,服務(wù)器在處理請(qǐng)求的過(guò)程中發(fā)生了錯(cuò)誤
- 500 服務(wù)器內(nèi)部錯(cuò)誤
- 502 Bad Gateway 作為網(wǎng)關(guān)或者代理工作的服務(wù)器嘗試執(zhí)行請(qǐng)求時(shí)罢低,從遠(yuǎn)程服務(wù)器接收到了一個(gè)無(wú)效的響應(yīng)
RTT
- index.json (配置當(dāng)前頁(yè)面標(biāo)題和引入組件等)纤壁;
- index.wxml (頁(yè)面結(jié)構(gòu));
- index.wxss (頁(yè)面樣式表)捺信;
- index.js (頁(yè)面的邏輯酌媒,請(qǐng)求和數(shù)據(jù)處理等);
GET /images/logo.gif HTTP/1.1
- 通用首部
- 請(qǐng)求首部
- 響應(yīng)首部
- 實(shí)體首部
- 304 Not Modified 所請(qǐng)求的資源未修改吠式,服務(wù)器返回此狀態(tài)碼時(shí)陡厘,不會(huì)返回任何資源。
- 400 客戶(hù)端請(qǐng)求的語(yǔ)法錯(cuò)誤糙置,服務(wù)端無(wú)法理解
- 403 Forbidden 服務(wù)器理解請(qǐng)求客戶(hù)端的請(qǐng)求,但是拒絕執(zhí)行此請(qǐng)求
- 404 Not Found 服務(wù)器無(wú)法根據(jù)客戶(hù)端的請(qǐng)求找到資源(網(wǎng)頁(yè))
- 500 服務(wù)器內(nèi)部錯(cuò)誤
- 502 Bad Gateway 作為網(wǎng)關(guān)或者代理工作的服務(wù)器嘗試執(zhí)行請(qǐng)求時(shí)罢低,從遠(yuǎn)程服務(wù)器接收到了一個(gè)無(wú)效的響應(yīng)
往返時(shí)延,在計(jì)算機(jī)網(wǎng)絡(luò)中它也是一個(gè)重要的性能指標(biāo)胖笛,它表示從發(fā)送端發(fā)送數(shù)據(jù)開(kāi)始网持,到發(fā)送端收到來(lái)自接收端的確認(rèn)(接收端收到數(shù)據(jù)后便立即發(fā)送確認(rèn)),總共經(jīng)歷的時(shí)延;
UDP協(xié)議
只是數(shù)據(jù)報(bào)文的搬運(yùn)工长踊,不會(huì)對(duì)報(bào)文進(jìn)行拆分和拼接操作功舀,不保證有序且不丟失的傳遞到對(duì)端
- 面向無(wú)連接
- 不可靠 -> 高效
在直播行業(yè)和即時(shí)對(duì)戰(zhàn)游戲等實(shí)時(shí)性要求高的行業(yè),UDP協(xié)議使用廣泛
TCP協(xié)議
TCP 基本是和 UDP 反著來(lái)身弊,建立連接斷開(kāi)連接都需要先需要進(jìn)行握手辟汰。在傳輸數(shù)據(jù)的過(guò)程中,通過(guò)各種算法保證數(shù)據(jù)的可靠性阱佛,當(dāng)然帶來(lái)的問(wèn)題就是相比 UDP 來(lái)說(shuō)不那么的高效帖汞。是全雙工協(xié)議。
標(biāo)識(shí)符
- URG=1:該字段為一表示本數(shù)據(jù)報(bào)的數(shù)據(jù)部分包含緊急信息凑术,是一個(gè)高優(yōu)先級(jí)數(shù)據(jù)報(bào)文翩蘸,此時(shí)緊急指針有效。緊急數(shù)據(jù)一定位于當(dāng)前數(shù)據(jù)包數(shù)據(jù)部分的最前面淮逊,緊急指針標(biāo)明了緊急數(shù)據(jù)的尾部催首。
- ACK=1:代表確認(rèn)接受,確認(rèn)號(hào)字段有效扶踊。此外,TCP 還規(guī)定在連接建立后傳送的所有報(bào)文段都必須把 ACK 置為一郎任。
- PSH=1:該字段為一表示接收端應(yīng)該立即將數(shù)據(jù) push 給應(yīng)用層秧耗,而不是等到緩沖區(qū)滿后再提交。
- RST=1:該字段為一表示當(dāng)前 TCP 連接出現(xiàn)嚴(yán)重問(wèn)題舶治,可能需要重新建立 TCP 連接分井,也可以用于拒絕非法的報(bào)文段和拒絕連接請(qǐng)求。
- SYN=1:代表請(qǐng)求創(chuàng)立連接歼疮,當(dāng)SYN=1杂抽,ACK=0時(shí),表示當(dāng)前報(bào)文段是一個(gè)連接請(qǐng)求報(bào)文韩脏。當(dāng)SYN=1缩麸,ACK=1時(shí),表示當(dāng)前報(bào)文段是一個(gè)同意建立連接的應(yīng)答報(bào)文赡矢。
- FIN=1:代表請(qǐng)求釋放連接杭朱。
- seq:序列號(hào),什么意思呢吹散?當(dāng)發(fā)送一個(gè)數(shù)據(jù)時(shí)弧械,數(shù)據(jù)是被拆成多個(gè)數(shù)據(jù)包來(lái)發(fā)送,序列號(hào)就是對(duì)每個(gè)數(shù)據(jù)包進(jìn)行編號(hào)空民,這樣接受方才能對(duì)數(shù)據(jù)包進(jìn)行再次拼接刃唐。
- ack:這個(gè)代表下一個(gè)數(shù)據(jù)包的編號(hào),這也就是為什么第二請(qǐng)求時(shí)界轩,ack是seq + 1(tip: ack和ACK代表的意思不同)
三次握手
客戶(hù)端 ------ SYN = 1, ACK = 0, seq = x ------- > 服務(wù)端
客戶(hù)端 < ----- SYN = 1, ACK = 1, seq = y, ack = x + 1 -------- 服務(wù)端
客戶(hù)端 ------ ACK = 1, seq = x + 1, ack = y + 1------- > 服務(wù)端
四次揮手
客戶(hù)端 ------ FIN ------- > 服務(wù)端
客戶(hù)端 < ----- ACK -------- 服務(wù)端
客戶(hù)端 < ----- FIN -------- 服務(wù)端
客戶(hù)端 ------ ACK ------- > 服務(wù)端
ARQ協(xié)議
ARQ協(xié)議其實(shí)就是超時(shí)重傳機(jī)制画饥。通過(guò)確認(rèn)和超時(shí)重傳機(jī)制保證數(shù)據(jù)的正確送達(dá)。
- 停止等待ARQ協(xié)議
- 連續(xù)ARQ協(xié)議
連續(xù)ARQ協(xié)議 - > 滑動(dòng)窗口
發(fā)送端窗口包含已發(fā)送但未收到應(yīng)答的數(shù)據(jù)
和待發(fā)送的數(shù)據(jù)
發(fā)送端窗口是由接收窗口剩余大小決定的浊猾。接收方會(huì)把當(dāng)前接收窗口的剩余大小寫(xiě)入應(yīng)答報(bào)文抖甘,發(fā)送端收到應(yīng)答后根據(jù)該值和當(dāng)前網(wǎng)絡(luò)擁塞情況設(shè)置發(fā)送窗口的大小,所以發(fā)送窗口的大小是不斷變化的葫慎。
滑動(dòng)窗口解決了數(shù)據(jù)的丟包衔彻、順序不對(duì)和流量控制問(wèn)題
擁塞處理
- 慢開(kāi)始算法
- 擁塞避免算法
- 快速重傳
- 快速恢復(fù)
七、面向?qū)ο?/h4>
面向?qū)ο蟮幕疽?/h5>
繼承
封裝
和多態(tài)
JS適合用來(lái)面向?qū)ο髥幔?/h5>
你在工作中是如何使用面向?qū)ο笏枷氲模?/h5>
明天需要上班偷办,后續(xù)跟進(jìn)補(bǔ)充艰额!