大廠面試題分享 面試題庫
前后端面試題庫 (面試必備) 推薦:★★★★★
地址:前端面試題庫??web前端面試題庫 VS java后端面試題庫大全文章來源地址http://www.zghlxwxcb.cn/news/detail-486184.html
html語義化的理解
-
代碼結構:?使頁面在沒有css的情況下,也能夠呈現(xiàn)出好的內(nèi)容結構
-
有利于SEO:?爬蟲根據(jù)標簽來分配關鍵字的權重,因此可以和搜索引擎建立良好的溝通,幫助爬蟲抓取更多的有效信息
-
方便其他設備解析:?如屏幕閱讀器、盲人閱讀器、移動設備等,以有意義的方式來渲染頁面
-
便于團體的開發(fā)和維護:?語義化使代碼更具有可讀性,讓其他開發(fā)人員更加理解你的html結構,減少差異化。遵循?W3C?標準的團隊都遵循這個標準。
常用的語義元素有:header、nav、main、footer、article、section、aside
更多的語義化標簽可以參閱:developer.mozilla.org/en-US/docs/…
iframe
iframe稱之為嵌入式框架、嵌入式框架可以把完整的網(wǎng)頁內(nèi)容嵌入到現(xiàn)有的網(wǎng)頁中。
優(yōu)點
- 重載頁面時不需要重載整個頁面只需要重載頁面中的一個框架頁
- 可以使腳本、可以并行下載
- 可以實現(xiàn)跨子域通信
缺點
- 會產(chǎn)生很多頁面,不容易管理
- 調(diào)用外部頁面,需要額外調(diào)用?CSS,給頁面帶來額外的請求次數(shù)
- iframe 會阻塞主頁面的 onload 事件
- 瀏覽器的后退按鈕無效
- 無法被一些搜索引擎索引識別
- 多數(shù)小型的移動設備無法完全顯示框架
BOM和DOM分別是什么
BOM是瀏覽器對象模型:?用來獲取或設置瀏覽器的屬性、行為。例如:新建窗口、獲取屏幕分辨率、瀏覽器版本號等
DOM是文檔對象模型:?用來獲取或設置文檔中標簽的屬性、例如獲取或者設置input表單的value值
CSS盒模型
盒模型都是由四個部分組成的,分別是margin、border、padding和content
標準盒模型和IE盒模型的區(qū)別在于設置width和height時,所對應的范圍不同:
- 標準盒模型的width和height屬性的范圍只包含了content,
- IE盒模型的width和height屬性的范圍包含了border、padding和content。
可以通過修改元素的box-sizing屬性來改變元素的盒模型:
-
box-sizing: content-box
表示標準盒模型(默認值) -
box-sizing: border-box
表示IE盒模型(怪異盒模型)
css級別順序
!important > 行內(nèi)樣式 > ID選擇器 > 類選擇器 > 標簽 > 通配符 > 繼承 > 瀏覽器默認屬性
css有哪些屬性不會被繼承
-
display
:指定元素如何顯示,如 block、inline、none 等,不會被繼承。 -
float
:指定元素的浮動方式,如 left、right,不會被繼承。 -
clear
:指定元素旁邊不允許浮動的元素,如 left、right、both、none,不會被繼承。 -
position
:指定元素的定位方式,如 relative、absolute、fixed 等,不會被繼承。 -
z-index
:指定元素的堆疊順序,不會被繼承。 -
overflow
:指定元素內(nèi)容溢出時的處理方式,如 visible、hidden、scroll、auto 等,不會被繼承。 -
columns
:指定多列布局的列數(shù)、寬度等屬性,不會被繼承。 - 等等......
怎么讓一個?div?水平垂直居中
- 通過絕對定位實現(xiàn)垂直居中
- 通過?transform?實現(xiàn)垂直居中
- 使用彈性盒子居中
BFC
所謂?BFC,指的是一個獨立的布局環(huán)境,BFC?內(nèi)部的元素布局與外部互不影響。
觸發(fā)?BFC?的方式有很多,常見的有:
- 設置浮動
- overflow?設置為?auto、scroll、hidden
- positon?設置為?absolute、fixed
常見BFC的應用
- 解決浮動元素令父元素高度坍塌的問題
- 解決非浮動元素被浮動元素覆蓋問題
- 解決外邊距垂直方向重合問題
JS?的基本數(shù)據(jù)類型有哪些?基本數(shù)據(jù)類型和引用數(shù)據(jù)類型的區(qū)別
基本數(shù)據(jù)類型
JavaScript共有八種數(shù)據(jù)類型,分別是?Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt
這些數(shù)據(jù)可以分為原始數(shù)據(jù)類型和引用數(shù)據(jù)類型:
- 棧:原始數(shù)據(jù)類型(Undefined、Null、Boolean、Number、String)
- 堆:引用數(shù)據(jù)類型(對象、數(shù)組和函數(shù))
基本數(shù)據(jù)類型和引用數(shù)據(jù)類型的區(qū)別
-
訪問方式:
- 原始值:訪問到的是值
- 引用值:訪問到的是引用地址 (
js不允許直接訪問保存在堆中的對象、首先得到在堆中的地址,然后按照這個地址去獲得對象的值
)
-
比較方式:
- 原始值:比較的是值
- 引用值: 比較的是引用的地址
-
變量賦值:
- 原始值賦值:賦值的是新值,與原來互不影響
- 引用值賦值:賦值的是地址,指向原值所在堆內(nèi)存中的地址
-
動態(tài)屬性:
- 原始值:賦值的是值
- 引用值:賦值的是地址
Js數(shù)據(jù)類型檢測的方式有哪些
-
typeof
- 其中數(shù)組、對象、null都會被判斷為object,其他判斷都正確
- typeof返回的類型都是字符串形式
-
instanceof
-
instanceof
可以正確判斷對象的類型,其內(nèi)部運行機制是判斷在其原型鏈中能否找到該類型的原型
-
-
constructor
-
Object.prototype.toString.call()
-
Object.prototype.toString.call()
?使用 Object 對象的原型方法 toString 來判斷數(shù)據(jù)類型:
-
常用的的js方法
-
fill方法:用某個數(shù)據(jù)填充數(shù)組
-
pop方法:刪除數(shù)組的最后一個元素,并返回這個元素
-
push方法:在數(shù)組的末尾添加一個或多個元素,并放回數(shù)組的新長度
-
reverse方法:顛倒數(shù)組中的元素排列順序
-
shift方法:刪除數(shù)組的第一個元素,并返回這個元素
-
sort方法:對數(shù)組元素進行隨機排序,并返回當前數(shù)組
-
splice方法:在任意的位置給數(shù)組添加或刪除任意各元素
-
unshift方法:在數(shù)組的開頭添加一個或者多個元素,并返回數(shù)組的新長度
純函數(shù)、無副作用函數(shù):不會導致當前對象發(fā)生改變
- concat方法:連接倆個數(shù)組
- includes方法:數(shù)組中是否包含滿足條件的元素
- join方法:連接所有數(shù)組元素組成一個字符串
- slice方法:抽取當前數(shù)組中的一段元素組合成一個新數(shù)組
- indexOf方法:返回數(shù)組中第一個與指定值相等的元素的索引,如果找不到這樣的元素,則返回-1
- lastIndexOf方法:返回數(shù)組中最后一個(從右邊數(shù)第一個)與指定值相等的元素的索引,如果找不到這樣的元素,則返回-1
- forEach方法:為數(shù)組中的每個元素執(zhí)行一次回調(diào)函數(shù)
- every方法:如果數(shù)組中每個元素都滿足測試函數(shù),則返回true,否則返回false
- some方法:數(shù)組中至少有一個元素滿足條件
- filter方法:過濾,得到滿足條件的元素組成的新數(shù)組
- find方法:找到第一個滿足測試函數(shù)的元素,并返回那個元素的值,如果找不到,則返回undefined
- findIndex方法:查找第一個滿足條件的元素,返回元素的下標
- map方法:映射,將數(shù)組的每一項映射稱為另外一項
- reduce方法:統(tǒng)計,累計
map和forEach的區(qū)別
forEach 會修改原來的數(shù)組,而map方法會得到一個新的數(shù)組并返回。
new操作符都做了哪些事?
new?運算符創(chuàng)建一個用戶定義的對象類型的實例或具有構造函數(shù)的內(nèi)置對象的實例。
new?關鍵字會進行如下的操作:
- 創(chuàng)建一個空的簡單?JavaScript?對象,即 { }
- 鏈接該對象到另一個對象(即設置該對象的原型對象)
- 將步驟1 新創(chuàng)建的對象作為?this?的上下文
- 如果該函數(shù)沒有返回對象,則返回?this。
ES6?新增哪些東西
- 箭頭函數(shù)
- 字符串模板
- 支持模塊化(import、export)
- 類(class、constructor、extends)
- let、const?關鍵字
- 新增一些數(shù)組、字符串等內(nèi)置構造函數(shù)方法,例如?Array.from、Array.of?、Math.sign、Math.trunc?等
- 新增一些語法,例如擴展操作符、解構、函數(shù)默認參數(shù)等
- 新增一種基本數(shù)據(jù)類型?Symbol
- 新增元編程相關,例如?proxy、Reflect
- Set?和?Map?數(shù)據(jù)結構
- Promise
- Generator?生成器
Map和Set的使用及區(qū)別
Map
Map存儲的是一個鍵值對的集合,支持的所有數(shù)據(jù)類型做為鍵
const map = new Map([['key1','value1'],['key2','value2']]);
map.set('myKey', 'myKey的鍵值');
// {'key1' => 'value1', 'key2' => 'value2', 'mykey' => 'myKey的鍵值'}
Set
- 類似數(shù)組,值不重復的
- 可存儲任何類型
- 值不會進行類型轉換,5和“5”是不同的
const?s1?=?new?Set(["a","b","c","d"]);
s1.add("f");//添加f
s1.delete("a");//刪除a
console.log(s1.has("b"));//是否含有b,返回布爾值
s1.clear();//
let const var 的區(qū)別?什么是塊級作用域?如何用?
-
var
?定義的變量,是函數(shù)作用域,沒有塊的概念,可以跨塊訪問, 不能跨函數(shù)訪問,有變量提升。 -
let
?定義的變量,只能在塊作用域里訪問,不能跨塊訪問,也不能跨函數(shù)訪問,無變量提升,不可以重復聲明。 -
const
?用來定義常量,使用時必須初始化(即必須賦值),只能在塊作用域里訪問,而且不能修改,無變量提升,不可以重復聲明。 -
var
不存在暫時性死區(qū),let
和const
存在暫時性死區(qū) -
let
和const
創(chuàng)建的全局變量沒有給window設置相應的屬性
暫時性死區(qū):使用?let / const?命令聲明變量之前,該變量都是不可用的
箭頭函數(shù)與普通函數(shù)的區(qū)別
-
箭頭函數(shù)沒有自己的this、會捕獲其所在的上下文的this值,作為自己的this值
-
箭頭函數(shù)繼承來的this指向永遠不會改變
-
call()、apply()、bind()等方法不能改變箭頭函數(shù)中this的指向
-
箭頭函數(shù)是匿名函數(shù),不能作為構造函數(shù),不能使用new
-
箭頭函數(shù)沒有自己的arguments
-
箭頭函數(shù)沒有prototype(原型)
-
箭頭函數(shù)不能用作Generator函數(shù),不能使用yeild關鍵字
bind,apply,call三者的區(qū)別
-
三者都可以改變函數(shù)的
this
對象指向 -
三者第一個參數(shù)都是
this
要指向的對象,如果如果沒有這個參數(shù)或參數(shù)為undefined
或null
,則默認指向全局window
-
三者都可以傳參,但是
apply
是數(shù)組,而call
是參數(shù)列表,且apply
和call
是一次性傳入?yún)?shù),而bind
可以分為多次傳入 -
bind
是返回綁定this之后的函數(shù),apply
、call
?則是立即執(zhí)行
是否了解?JavaScript?中的包裝類型?
包裝對象 : 就是當基本類型以對象的方式去使用時,JavaScript?會轉換成對應的包裝類型,相當于?new?一個對象,內(nèi)容和基本類型的內(nèi)容一樣,然后當操作完成再去訪問的時候,這個臨時對象會被銷毀,然后再訪問時候就是?undefined
代碼理解:
var str = 'hello';
str.number = 10; //假設我們想給字符串添加一個屬性 number ,后臺會有如下步驟
(
var _str = new String('hello'); // 1 找到對應的包裝對象類型,然后通過包裝對象創(chuàng)建出一個和基本類型值相同的對象
_str.number = 10; // 2 通過這個對象調(diào)用包裝對象下的方法 但結果并沒有被任何東西保存
_str =null; // 3 這個對象又被銷毀
)
console.log(str.number); // undefined 當執(zhí)行到這一句的時候,因為基本類型本來沒有屬性,后臺又會重新重復上面的步驟
(
var str = new String('hello');// 1 找到基本包裝對象,然后又新開辟一個內(nèi)存,創(chuàng)建一個值為 hello 對象
str.number = undefined;// 2 因為包裝對象下面沒有 number 這個屬性,所以又會重新添加,因為沒有值,所以值是未定義;然后彈出結果
str =null; // 3 這個對象又被銷毀
)
JS?中如何進行數(shù)據(jù)類型的轉換?
類型轉換可以分為兩種,隱性轉換和顯性轉換
顯性轉換
主要分為三大類:數(shù)值類型、字符串類型、布爾類型
三大類的原始類型值的轉換規(guī)則我就不一一列舉了,更多詳情文章鏈接??juejin.cn/post/695617…
數(shù)值類型(引用類型轉換)
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5
第一步,調(diào)用對象自身的`valueOf`方法。如果返回原始類型的值,則直接對該值使用`Number`函數(shù),不再進行后續(xù)步驟。
第二步,如果`valueOf`方法返回的還是對象,則改為調(diào)用對象自身的`toString`方法。如果`toString`方法返回原始類型的值,
則對該值使用`Number`函數(shù),不再進行后續(xù)步驟。
第三步,如果`toString`方法返回的是對象,就報錯。
補充一點:`valueOf`和`toString`方法,都是可以自定義的
字符串類型(引用類型轉換)
String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"
`String`方法背后的轉換規(guī)則,與`Number`方法基本相同,只是互換了`valueOf`方法和`toString`方法的執(zhí)行順序。
隱性轉換
類型 | 轉換前 | 轉換后 |
---|---|---|
number | 4 | 4 |
string | "1" | 1 |
string | "" | 0 |
boolean | true | 1 |
boolean | false | 0 |
undefined | undefined | NaN |
null | null | 0 |
詳情看上方??文章鏈接
閉包
閉包是指有權訪問另一個函數(shù)作用域中的變量的函數(shù)?———— 《JavaScript高級程序設計》
-
閉包用途:
- 能夠訪問函數(shù)定義時所在的詞法作用域(阻止其被回收)
- 私有變量化
- 模擬塊級作用域
- 創(chuàng)建模塊
-
閉包缺點:閉包調(diào)用函數(shù)的變量,并且這個變量在函數(shù)執(zhí)行完之后,不能釋放,會導致函數(shù)的變量一直保存在內(nèi)存中,過多的閉包可能會導致內(nèi)存泄漏。
-
解決:變量設置成null
原型和原型鏈
原型
- 每個實例對象都有一個?proto?屬性,該屬性指向自己的原型對象
- 每個構造函數(shù)都有一個?prototype?屬性,該屬性指向實例對象的原型對象
- 原型對象里的?constructor?指向構造函數(shù)本身
原型鏈
當試圖訪問一個對象的屬性時,它不僅僅在該對象上搜尋,還會搜尋該對象的原型,以及該對象的原型的原型,依次層層向上搜索,直到找到一個名字匹配的屬性或到達原型鏈的末尾null
作用域和作用域鏈的理解
作用域
(1)全局作用域
- 最外層函數(shù)和最外層函數(shù)外面定義的變量擁有全局作用域
- 所有未定義直接賦值的變量自動聲明為全局作用域
- 所有window對象的屬性擁有全局作用域
- 全局作用域有很大的弊端,過多的全局作用域變量會污染全局命名空間,容易引起命名沖突。
(2)函數(shù)作用域
- 函數(shù)作用域聲明在函數(shù)內(nèi)部的變量,一般只有固定的代碼片段可以訪問到
- 作用域是分層的,內(nèi)層作用域可以訪問外層作用域,反之不行
(3)塊級作用域
- 使用ES6中新增的let和const指令可以聲明塊級作用域,塊級作用域可以在函數(shù)中創(chuàng)建也可以在一個代碼塊中的創(chuàng)建(由
{ }
包裹的代碼片段) - let和const聲明的變量不會有變量提升,也不可以重復聲明
- 在循環(huán)中比較適合綁定塊級作用域,這樣就可以把聲明的計數(shù)器變量限制在循環(huán)內(nèi)部。
作用域鏈
- 在當前作用域中查找所需變量,但是該作用域沒有這個變量,那這個變量就是自由變量。
- 如果在自己作用域找不到該變量就去父級作用域查找,依次向上級作用域查找,直到訪問到window對象就被終止,這一層層的關系就是作用域鏈。
作用域鏈有一個非常重要的特性,那就是作用域中的值是在函數(shù)創(chuàng)建的時候,就已經(jīng)被存儲了,是靜態(tài)的。
宏任務和微任務
- 常見的宏任務有:setTimeout、setInterval、requestAnimationFrame、script等。
- 常見的微任務有:new Promise( ).then(回調(diào))、MutationObserver?等。
宏任務和微任務的執(zhí)行流程,總結起來就是:
js在調(diào)用時,優(yōu)先取出微任務,并且在執(zhí)行過程中如果創(chuàng)建了新的作業(yè),則放在本次執(zhí)行完后緊接著調(diào)用,微任務執(zhí)行完成后,再取出宏任務執(zhí)行
哪些情況會導致內(nèi)存泄漏
以下四種情況會造成內(nèi)存的泄漏:
- 意外的全局變量:?由于使用未聲明的變量,而意外的創(chuàng)建了一個全局變量,而使這個變量一直留在內(nèi)存中無法被回收。
- 被遺忘的計時器或回調(diào)函數(shù):?設置了 setInterval 定時器,而忘記取消它,如果循環(huán)函數(shù)有對外部變量的引用的話,那么這個變量會被一直留在內(nèi)存中,而無法被回收。
- 脫離 DOM 的引用:?獲取一個 DOM 元素的引用,而后面這個元素被刪除,由于一直保留了對這個元素的引用,所以它也無法被回收。
- 閉包:?不合理的使用閉包,從而導致某些變量一直被留在內(nèi)存當中。
請介紹一下?JavaScript?中的垃圾回收站機制
JavaScript?具有自動垃圾回收機制。垃圾收集器會按照固定的時間間隔周期性的執(zhí)行。
JavaScript?常見的垃圾回收方式:標記清除、引用計數(shù)方式。
標記清除方式:
- 工作原理:當變量進入環(huán)境時,將這個變量標記為“進入環(huán)境”。當變量離開環(huán)境時,則將其標記為“離開環(huán)境”。標記“離開環(huán)境”的就回收內(nèi)存。
- 工作流程:
- 垃圾回收器,在運行的時候會給存儲在內(nèi)存中的所有變量都加上標記;
- 去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標記;
- 被加上標記的會被視為準備刪除的變量;
- 垃圾回收器完成內(nèi)存清理工作,銷毀那些帶標記的值并回收他們所占用的內(nèi)存空間。
引用計數(shù)方式:
- 工作原理:跟蹤記錄每個值被引用的次數(shù)。
- 工作流程:
- 聲明了一個變量并將一個引用類型的值賦值給這個變量,這個引用類型值的引用次數(shù)就是?1;
- 同一個值又被賦值給另一個變量,這個引用類型值的引用次數(shù)加?1;
- 當包含這個引用類型值的變量又被賦值成另一個值了,那么這個引用類型值的引用次數(shù)減?1;
- 當引用次數(shù)變成?0?時,說明沒辦法訪問這個值了;
- 當垃圾收集器下一次運行時,它就會釋放引用次數(shù)是?0?的值所占的內(nèi)存。
防抖,節(jié)流是什么
- 函數(shù)防抖(debounce),指的是短時間內(nèi)多次觸發(fā)同一事件,只執(zhí)行最后一次,或者只執(zhí)行最開始的一次,中間的不執(zhí)行
- 函數(shù)節(jié)流(throttle),指連續(xù)觸發(fā)事件但是在?n?秒中只執(zhí)行一次函數(shù)。即?2n?秒內(nèi)執(zhí)行?2?次...
深拷貝和淺拷貝
淺拷貝
只是拷貝了基本類型的數(shù)據(jù),而引用類型數(shù)據(jù),復制后也是會發(fā)生引用,我們把這種拷貝叫做淺拷貝(淺復制)淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內(nèi)存。
淺拷貝:
- 直接賦值
- Object.assign?方法:可以把任意多個的源對象自身的可枚舉屬性拷貝給目標對象,然后返回目標對象。當拷貝的?object?只有一層的時候,是深拷貝,但是當拷貝的對象屬性值又是一個引用時,換句話說有多層時,就是一個淺拷貝。
- ES6?擴展運算符,當?object?只有一層的時候,也是深拷貝。有多層時是淺拷貝。
- Array.prototype.concat?方法
- Array.prototype.slice?方法
深拷貝
在堆中重新分配內(nèi)存,并且把源對象所有屬性都進行新建拷貝,以保證深拷貝的對象的引用圖不包含任何原有對象或對象圖上的任何對象,拷貝后的對象與原來的對象是完全隔離,互不影響。
深拷貝:
-
$.extend(deep,target,object1,objectN)
?,將?deep
?設置為?true
-
JSON.parse(JSON.stringify)
?:用?JSON.stringify
?將對象轉成JSON
字符串,再用?JSON.parse
?方法把字符串解析成對象,一去一來,新的對象產(chǎn)生了,而且對象會開辟新的棧,實現(xiàn)深拷貝。這種方法雖然可以實現(xiàn)數(shù)組或對象深拷貝,但不能處理函數(shù)。 - 手寫遞歸
實例代碼如下:
function deepCopy(oldObj, newobj) {
for (var key in oldObj) {
var item = oldObj[key];
// 判斷是否是對象
if (item instanceof Object) {
if (item instanceof Function) {
newobj[key] = oldObj[key];
} else {
newobj[key] = {}; //定義一個空的對象來接收拷貝的內(nèi)容
deepCopy(item, newobj[key]); //遞歸調(diào)用
}
// 判斷是否是數(shù)組
} else if (item instanceof Array) {
newobj[key] = []; //定義一個空的數(shù)組來接收拷貝的內(nèi)容
deepCopy(item, newobj[key]); //遞歸調(diào)用
} else {
newobj[key] = oldObj[key];
}
}
}
事件冒泡和事件捕獲
事件冒泡
微軟提出了名為事件冒泡(event bubbling)的事件流。事件冒泡可以形象地比喻為把一顆石頭投入水中,泡泡會一直從水底冒出水面。也就是說,事件會從最內(nèi)層的元素開始發(fā)生,一直向上傳播,直到document對象。
p -> div -> body -> html -> document
事件捕獲
網(wǎng)景提出另一種事件流名為事件捕獲(event capturing)。與事件冒泡相反,事件會從最外層開始發(fā)生,直到最具體的元素。
document -> html -> body -> div -> p
HTTP狀態(tài)碼
狀態(tài)碼的類別:
類別 | 原因 | 描述 |
---|---|---|
1xx | Informational(信息性狀態(tài)碼) | 接受的請求正在處理 |
2xx | Success(成功狀態(tài)碼) | 請求正常處理完畢 |
3xx | Redirection(重定向狀態(tài)碼) | 需要進行附加操作一完成請求 |
4xx | Client Error (客戶端錯誤狀態(tài)碼) | 服務器無法處理請求 |
5xx | Server Error(服務器錯誤狀態(tài)碼) | 服務器處理請求出錯 |
Http和Https區(qū)別
-
HTTP
?的URL 以http:// 開頭,而HTTPS 的URL 以https:// 開頭 -
HTTP
?是不安全的,而 HTTPS 是安全的 -
HTTP
?標準端口是80 ,而 HTTPS 的標準端口是443 -
在OSI
?網(wǎng)絡模型中,HTTP工作于應用層,而HTTPS 的安全傳輸機制工作在傳輸層 -
HTTP
?無法加密,而HTTPS 對傳輸?shù)臄?shù)據(jù)進行加密 -
HTTP
無需證書,而HTTPS 需要CA機構wosign的頒發(fā)的SSL證書
GET 和 POST 的區(qū)別
從 http 協(xié)議的角度來說,GET 和 POST 它們都只是請求行中的第一個單詞,除了語義不同,其實沒有本質的區(qū)別。
之所以在實際開發(fā)中會產(chǎn)生各種區(qū)別,主要是因為瀏覽器的默認行為造成的。
受瀏覽器的影響,在實際開發(fā)中,GET 和 POST 有以下區(qū)別:
-
瀏覽器在發(fā)送 GET 請求時,不會附帶請求體
-
GET 請求的傳遞信息量有限,適合傳遞少量數(shù)據(jù);POST 請求的傳遞信息量是沒有限制的,適合傳輸大量數(shù)據(jù)。
-
GET 請求只能傳遞 ASCII 數(shù)據(jù),遇到非 ASCII 數(shù)據(jù)需要進行編碼;POST 請求沒有限制
-
大部分 GET 請求傳遞的數(shù)據(jù)都附帶在 path 參數(shù)中,能夠通過分享地址完整的重現(xiàn)頁面,但同時也暴露了數(shù)據(jù),若有敏感數(shù)據(jù)傳遞,不應該使用 GET 請求,至少不應該放到 path 中
-
刷新頁面時,若當前的頁面是通過 POST 請求得到的,則瀏覽器會提示用戶是否重新提交。若是 GET 請求得到的頁面則沒有提示。
-
GET 請求的地址可以被保存為瀏覽器書簽,POST 不可以
瀏覽器渲染機制、重繪、重排
網(wǎng)頁生成過程:
-
HTML
被HTML解析器解析成DOM
?樹 -
css
則被css解析器解析成CSSOM?
樹 - 結合
DOM
樹和CSSOM
樹,生成一棵渲染樹(Render Tree
) - 生成布局(
flow
),即將所有渲染樹的所有節(jié)點進行平面合成 - 將布局繪制(
paint
)在屏幕上
重排(也稱回流):??當DOM的變化影響了元素的幾何屬性(DOM對象的位置和尺寸大?。瑸g覽器需要重新計算元素的幾何屬性,將其安放在界面中正確的位置,這個過程就叫回流。觸發(fā):
- 添加或者刪除可見的DOM元素
- 元素尺寸改變——邊距、填充、邊框、寬度和高度
重繪:?當一個元素的外觀發(fā)生了改變,但沒有改變布局,重新把元素外觀繪制出來的過程,叫做重繪,觸發(fā):
- 改變元素的color、background、box-shadow屬性
url按下回車之后發(fā)生了什么
1 解析域名
2 緩存判斷 --有資源直接返回、否則向服務器發(fā)起新的請求
3 DNS解析
4 獲取MAC地址
5 會把請求的內(nèi)容存儲到dns
6 TCP三次握手
7 HTTPS握手
8 返回數(shù)據(jù)
9 TCP四次揮手
cookie、sessionStorage、localStorage的區(qū)別
- cookie 可以設置失效時間
- localStorage 除非手動清除,否則永久保存
- sessionStorage 盡在當前網(wǎng)頁有效,關閉頁面就被清除
- cookie儲存大小是4k,localStorage和sessionStorage是5M
- 請求時:cookie自動攜帶HTTP頭部中,localStorage和sessionStorage僅在瀏覽器保存,不參與服務器通信
- cookie是由服務器寫入的,而sessionStorage、localStorage是由前端寫入的
- cookie用于儲存登錄信息,localStorage常用于不易變動的數(shù)據(jù),sessionStorage常用于檢查用戶是否是刷新進入頁面、如回復播放器進度條的功能
Promise.all和Promise.race的區(qū)別的使用場景
(1)Promise.all?Promise.all
可以將多個Promise
實例包裝成一個新的Promise實例。同時,成功和失敗的返回值是不同的,成功的時候返回的是一個結果數(shù)組,而失敗的時候則返回最先被reject失敗狀態(tài)的值。
Promise.all中傳入的是數(shù)組,返回的也是是數(shù)組,并且會將進行映射,傳入的promise對象返回的值是按照順序在數(shù)組中排列的,但是注意的是他們執(zhí)行的順序并不是按照順序的,除非可迭代對象為空。
需要注意,Promise.all獲得的成功結果的數(shù)組里面的數(shù)據(jù)順序和Promise.all接收到的數(shù)組順序是一致的,這樣當遇到發(fā)送多個請求并根據(jù)請求順序獲取和使用數(shù)據(jù)的場景,就可以使用Promise.all來解決。
(2)Promise.race
顧名思義,Promse.race就是賽跑的意思,意思就是說,Promise.race([p1, p2, p3])里面哪個結果獲得的快,就返回那個結果,不管結果本身是成功狀態(tài)還是失敗狀態(tài)。當要做一件事,超過多長時間就不做了,可以用這個方法來解決:
Promise.race([promise1,timeOutPromise(5000)]).then(res=>{})
同源策略
瀏覽器有一個重要的安全策略,稱之為同源策略
其中,協(xié)議、端口號、域名必須一致,,稱之為同源,兩個源不同,稱之為跨源或跨域
同源策略是指,若頁面的源和頁面運行過程中加載的源不一致時,出于安全考慮,瀏覽器會對跨域的資源訪問進行一些限制
如何解決跨域問題
-
jsonp
(利用script
標簽沒有跨域限制的漏洞實現(xiàn)。缺點:只支持GET
請求) -
CORS
(設置Access-Control-Allow-Origin
:指定可訪問資源的域名 -
Node
中間件代理 -
Nginx
反向代理
談談你對 TCP 三次握手和四次揮手的理解
TCP 協(xié)議通過三次握手建立可靠的點對點連接,具體過程是:
首先服務器進入監(jiān)聽狀態(tài),然后即可處理連接
-
第一次握手:建立連接時,客戶端發(fā)送 syn 包到服務器,并進入 SYN_SENT 狀態(tài),等待服務器確認。在發(fā)送的包中還會包含一個初始序列號 seq。此次握手的含義是客戶端希望與服務器建立連接。
-
第二次握手:服務器收到 syn 包,然后回應給客戶端一個 SYN+ACK 包,此時服務器進入 SYN_RCVD 狀態(tài)。此次握手的含義是服務端回應客戶端,表示已收到并同意客戶端的連接請求。
-
第三次握手:客戶端收到服務器的 SYN 包后,向服務器再次發(fā)送 ACK 包,并進入 ESTAB_LISHED 狀態(tài)。
最后,服務端收到客戶端的 ACK 包,于是也進入 ESTAB_LISHED 狀態(tài),至此,連接建立完成
當需要關閉連接時,需要進行四次揮手才能關閉
-
Client 向 Server 發(fā)送 FIN 包,表示 Client 主動要關閉連接,然后進入 FIN_WAIT_1 狀態(tài),等待 Server 返回 ACK 包。此后 Client 不能再向 Server 發(fā)送數(shù)據(jù),但能讀取數(shù)據(jù)。
-
Server 收到 FIN 包后向 Client 發(fā)送 ACK 包,然后進入 CLOSE_WAIT 狀態(tài),此后 Server 不能再讀取數(shù)據(jù),但可以繼續(xù)向 Client 發(fā)送數(shù)據(jù)。
-
Client 收到 Server 返回的 ACK 包后進入 FIN_WAIT_2 狀態(tài),等待 Server 發(fā)送 FIN 包。
-
Server 完成數(shù)據(jù)的發(fā)送后,將 FIN 包發(fā)送給 Client,然后進入 LAST_ACK 狀態(tài),等待 Client 返回 ACK 包,此后 Server 既不能讀取數(shù)據(jù),也不能發(fā)送數(shù)據(jù)。
-
Client 收到 FIN 包后向 Server 發(fā)送 ACK 包,然后進入 TIME_WAIT 狀態(tài),接著等待足夠長的時間(2MSL)以確保 Server 接收到 ACK 包,最后回到 CLOSED 狀態(tài),釋放網(wǎng)絡資源。
-
Server 收到 Client 返回的 ACK 包后便回到 CLOSED 狀態(tài),釋放網(wǎng)絡資源。
簡單的理解
三次握手
- 客戶端向服務端發(fā)信息:你能接收到我的信息嗎
- 服務端回復客戶端信息:我能收到你的信息,你能收到我的回復信息嗎
- 客戶信息向服務端回復:收到你的信息了,那我開始向你傳輸數(shù)據(jù)了
四次揮手
- 客戶端告訴服務端:數(shù)據(jù)發(fā)送完了
- 服務端回復客戶端:知道你發(fā)完了,我還沒接受完等一下
- 服務端回復客戶端:數(shù)據(jù)接收完了
- 客戶端回復服務端:知道你接收完成
?文章來源:http://www.zghlxwxcb.cn/news/detail-486184.html
大廠面試題分享 面試題庫
前后端面試題庫 (面試必備) 推薦:★★★★★
地址:前端面試題庫??web前端面試題庫 VS java后端面試題庫大全
到了這里,關于前端基礎面試題(HTML,CSS,JS)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!