常見前端基礎面試題(HTML,CSS,JS)
theme: smartblue highlight: androidstudio
html語義化的理解
-
程式碼結構: 使頁面在沒有css的情況下,也能夠呈現出好的內容結構
-
有利於SEO: 爬蟲根據標籤來分配關鍵字的權重,因此可以和搜尋引擎建立良好的溝通,幫助爬蟲抓取更多的有效資訊
- 方便其他裝置解析: 如螢幕閱讀器、盲人閱讀器、移動裝置等,以有意義的方式來渲染頁面
- 便於團體的開發和維護: 語義化使程式碼更具有可讀性,讓其他開發人員更加理解你的html結構,減少差異化。遵循 W3C 標準的團隊都遵循這個標準。
常用的語義元素有:header、nav、main、footer、article、section、aside
更多的語義化標籤可以參閱:http://developer.mozilla.org/en-US/docs/Web/HTML/Element
iframe
iframe稱之為嵌入式框架、嵌入式框架可以把完整的網頁內容嵌入到現有的網頁中。
優點
- 過載頁面時不需要過載整個頁面只需要過載頁面中的一個框架頁
- 可以使指令碼、可以並行下載
- 可以實現跨子域通訊
缺點
- 會產生很多頁面,不容易管理
- 呼叫外部頁面,需要額外呼叫 CSS,給頁面帶來額外的請求次數
- iframe 會阻塞主頁面的 onload 事件
- 瀏覽器的後退按鈕無效
- 無法被一些搜尋引擎索引識別
- 多數小型的移動裝置無法完全顯示框架
BOM和DOM分別是什麼
BOM是瀏覽器物件模型: 用來獲取或設定瀏覽器的屬性、行為。例如:新建視窗、獲取螢幕解析度、瀏覽器版本號等
DOM是文件物件模型: 用來獲取或設定文件中標籤的屬性、例如獲取或者設定input表單的value值
CSS盒模型
盒模型都是由四個部分組成的,分別是margin、border、padding和content
標準盒模型和IE盒模型的區別在於設定width和height時,所對應的範圍不同:
- 標準盒模型的width和height屬性的範圍只包含了content,
- IE盒模型的width和height屬性的範圍包含了border、padding和content。
可以通過修改元素的box-sizing屬性來改變元素的盒模型:
box-sizeing: content-box
表示標準盒模型(預設值)box-sizeing: border-box
表示IE盒模型(怪異盒模型)
怎麼讓一個 div 水平垂直居中
-
通過絕對定位實現垂直居中
-
通過 transform 實現垂直居中
- 使用彈性盒子居中
BFC
所謂 BFC,指的是一個獨立的佈局環境,BFC 內部的元素佈局與外部互不影響。
觸發 BFC 的方式有很多,常見的有:
- 設定浮動
- overflow 設定為 auto、scroll、hidden
- positon 設定為 absolute、fixed
常見BFC的應用
- 解決浮動元素令父元素高度坍塌的問題
- 解決非浮動元素被浮動元素覆蓋問題
- 解決外邊距垂直方向重合問題
JS 的基本資料型別有哪些?基本資料型別和引用資料型別的區別
基本資料型別
JavaScript共有八種資料型別,分別是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt
這些資料可以分為原始資料型別和引用資料型別:
- 棧:原始資料型別(Undefined、Null、Boolean、Number、String)
- 堆:引用資料型別(物件、陣列和函式)
基本資料型別和引用資料型別的區別
-
訪問方式:
- 原始值:訪問到的是值 - 引用值:訪問到的是引用地址 (`js不允許直接訪問儲存在堆中的物件、首先得到在堆中的地址,然後按照這個地址去獲得物件的值`)
-
比較方式:
- 原始值:比較的是值
- 引用值: 比較的是引用的地址
-
變數賦值:
- 原始值賦值:賦值的是新值,與原來互不影響
- 引用值賦值:賦值的是地址,指向原值所在堆記憶體中的地址
-
動態屬性:
- 原始值:賦值的是值
- 引用值:賦值的是地址
ES6 新增哪些東西
- 箭頭函式
- 字串模板
- 支援模組化(import、export)
- 類(class、constructor、extends)
- let、const 關鍵字
- 新增一些陣列、字串等內建建構函式方法,例如 Array.from、Array.of 、Math.sign、Math.trunc 等
- 新增一些語法,例如擴充套件操作符、解構、函式預設引數等
- 新增一種基本資料型別 Symbol
- 新增超程式設計相關,例如 proxy、Reflect
- Set 和 Map 資料結構
- Promise
- Generator 生成器
let const var 的區別?什麼是塊級作用域?如何用?
var
定義的變數,是函式作用域,沒有塊的概念,可以跨塊訪問, 不能跨函式訪問,有變數提升。let
定義的變數,只能在塊作用域裡訪問,不能跨塊訪問,也不能跨函式訪問,無變數提升,不可以重複宣告。-
const
用來定義常量,使用時必須初始化(即必須賦值),只能在塊作用域裡訪問,而且不能修改,無變數提升,不可以重複宣告。 -
var
不存在暫時性死區,let
和const
存在暫時性死區 let
和const
建立的全域性變數沒有給window設定相應的屬性
暫時性死區:使用 let / const 命令宣告變數之前,該變數都是不可用的
箭頭函式與普通函式的區別
- 箭頭函式沒有自己的this、會捕獲其所在的上下文的this值,作為自己的this值
- 箭頭函式繼承來的this指向永遠不會改變
-
call()、apply()、bind()等方法不能改變箭頭函式中this的指向
-
箭頭函式是匿名函式,不能作為建構函式,不能使用new
- 箭頭函式沒有自己的arguments
- 箭頭函式沒有prototype(原型)
- 箭頭函式不能用作Generator函式,不能使用yeild關鍵字
bind,apply,call三者的區別
-
三者都可以改變函式的
this
物件指向 -
三者第一個引數都是
this
要指向的物件,如果如果沒有這個引數或引數為undefined
或null
,則預設指向全域性window
- 三者都可以傳參,但是
apply
是陣列,而call
是引數列表,且apply
和call
是一次性傳入引數,而bind
可以分為多次傳入 bind
是返回繫結this之後的函式,apply
、call
則是立即執行
是否瞭解 JavaScript 中的包裝型別?
包裝物件 : 就是當基本型別以物件的方式去使用時,JavaScript 會轉換成對應的包裝型別,相當於 new 一個物件,內容和基本型別的內容一樣,然後當操作完成再去訪問的時候,這個臨時物件會被銷燬,然後再訪問時候就是 undefined
程式碼理解:
js
var str = 'hello';
str.number = 10; //假設我們想給字串新增一個屬性 number ,後臺會有如下步驟
(
var _str = new String('hello'); // 1 找到對應的包裝物件型別,然後通過包裝物件創建出一個和基本型別值相同的物件
_str.number = 10; // 2 通過這個物件呼叫包裝物件下的方法 但結果並沒有被任何東西儲存
_str =null; // 3 這個物件又被銷燬
)
console.log(str.number); // undefined 當執行到這一句的時候,因為基本型別本來沒有屬性,後臺又會重新重複上面的步驟
(
var str = new String('hello');// 1 找到基本包裝物件,然後又新開闢一個記憶體,建立一個值為 hello 物件
str.number = undefined;// 2 因為包裝物件下面沒有 number 這個屬性,所以又會重新新增,因為沒有值,所以值是未定義;然後彈出結果
str =null; // 3 這個物件又被銷燬
)
JS 中如何進行資料型別的轉換?
型別轉換可以分為兩種,隱性轉換和顯性轉換
顯性轉換
主要分為三大類:數值型別、字串型別、布林型別
三大類的原始型別值的轉換規則我就不一一列舉了,更多詳情文章連結👉http://juejin.cn/post/6956170676327677966
數值型別(引用型別轉換)
```js Number({a: 1}) // NaN Number([1, 2, 3]) // NaN Number([5]) // 5
第一步,呼叫物件自身的valueOf
方法。如果返回原始型別的值,則直接對該值使用Number
函式,不再進行後續步驟。
第二步,如果valueOf
方法返回的還是物件,則改為呼叫物件自身的toString
方法。如果toString
方法返回原始型別的值,
則對該值使用Number
函式,不再進行後續步驟。
第三步,如果toString
方法返回的是物件,就報錯。
補充一點:valueOf
和toString
方法,都是可以自定義的
```
字串型別(引用型別轉換)
```js String({a: 1}) // "[object Object]" String([1, 2, 3]) // "1,2,3"
String
方法背後的轉換規則,與Number
方法基本相同,只是互換了valueOf
方法和toString
方法的執行順序。
```
隱性轉換
型別 | 轉換前 | 轉換後 | | --------- | --------- | --- | | number | 4 | 4 | | string | "1" | 1 | | string | "" | 0 | | boolean | true | 1 | | boolean | false | 0 | | undefined | undefined | NaN | | null | null | 0
詳情看上方👆文章連結
閉包
閉包是指有權訪問另一個函式作用域中的變數的函式 ———— 《JavaScript高階程式設計》
-
閉包用途:
- 能夠訪問函式定義時所在的詞法作用域(阻止其被回收)
- 私有變數化
- 模擬塊級作用域
- 建立模組
-
閉包缺點:閉包呼叫函式的變數,並且這個變數在函式執行完之後,不能釋放,會導致函式的變數一直儲存在記憶體中,過多的閉包可能會導致記憶體洩漏。
-
解決:變數設定成null
原型和原型鏈
原型
- 每個物件都有一個 proto 屬性,該屬性指向自己的原型物件
- 每個建構函式都有一個 prototype 屬性,該屬性指向例項物件的原型物件
- 原型物件裡的 constructor 指向建構函式本身
原型鏈
當試圖訪問一個物件的屬性時,它不僅僅在該物件上搜尋,還會搜尋該物件的原型,以及該物件的原型的原型,依次層層向上搜尋,直到找到一個名字匹配的屬性或到達原型鏈的末尾null
作用域和作用域鏈的理解
作用域
(1)全域性作用域
- 最外層函式和最外層函式外面定義的變數擁有全域性作用域
- 所有未定義直接賦值的變數自動宣告為全域性作用域
- 所有window物件的屬性擁有全域性作用域
- 全域性作用域有很大的弊端,過多的全域性作用域變數會汙染全域性名稱空間,容易引起命名衝突。
(2)函式作用域
- 函式作用域宣告在函式內部的變零,一般只有固定的程式碼片段可以訪問到
- 作用域是分層的,內層作用域可以訪問外層作用域,反之不行
(3)塊級作用域
- 使用ES6中新增的let和const指令可以宣告塊級作用域,塊級作用域可以在函式中建立也可以在一個程式碼塊中的建立(由
{ }
包裹的程式碼片段) - let和const宣告的變數不會有變數提升,也不可以重複宣告
- 在迴圈中比較適合繫結塊級作用域,這樣就可以把宣告的計數器變數限制在迴圈內部。
作用域鏈
- 在當前作用域中查詢所需變數,但是該作用域沒有這個變數,那這個變數就是自由變數。
- 如果在自己作用域找不到該變數就去父級作用域查詢,依次向上級作用域查詢,直到訪問到window物件就被終止,這一層層的關係就是作用域鏈。
作用域鏈有一個非常重要的特性,那就是作用域中的值是在函式建立的時候,就已經被儲存了,是靜態的。
防抖和節流
我們在平時開發的時候,會有很多場景會頻繁觸發事件,比如說搜尋框實時發請求,onmousemove、resize、onscroll 等,有些時候,我們並不能或者不想頻繁觸發事件,這時候就應該用到函式防抖和函式節流。
函式防抖(debounce),指的是短時間內多次觸發同一事件,只執行最後一次,或者只執行最開始的一次,中間的不執行。
函式節流(throttle),指連續觸發事件但是在 n 秒中只執行一次函式。即 2n 秒內執行 2 次... 。節流如字面意思,會稀釋函式的執行頻率。
區別在於:防抖動是將多次執行變為最後一次執行,節流是將多次執行變成每隔一段時間執行
巨集任務和微任務
- 常見的巨集任務有:setTimeout、setInterval、requestAnimationFrame、script等。
- 常見的微任務有:new Promise( ).then(回撥)、MutationObserver 等。
巨集任務和微任務的執行流程,總結起來就是:
js在呼叫時,優先取出微任務,並且在執行過程中如果建立了新的作業,則放在本次執行完後緊接著呼叫,微任務執行完成後,再取出巨集任務執行
哪些情況會導致記憶體洩漏
以下四種情況會造成記憶體的洩漏:
- 意外的全域性變數: 由於使用未宣告的變數,而意外的建立了一個全域性變數,而使這個變數一直留在記憶體中無法被回收。
- 被遺忘的計時器或回撥函式: 設定了 setInterval 定時器,而忘記取消它,如果迴圈函式有對外部變數的引用的話,那麼這個變數會被一直留在記憶體中,而無法被回收。
- 脫離 DOM 的引用: 獲取一個 DOM 元素的引用,而後面這個元素被刪除,由於一直保留了對這個元素的引用,所以它也無法被回收。
- 閉包: 不合理的使用閉包,從而導致某些變數一直被留在記憶體當中。
請介紹一下 JavaScript 中的垃圾回收站機制
JavaScript 具有自動垃圾回收機制。垃圾收集器會按照固定的時間間隔週期性的執行。
JavaScript 常見的垃圾回收方式:標記清除、引用計數方式。
標記清除方式:
- 工作原理:當變數進入環境時,將這個變數標記為“進入環境”。當變數離開環境時,則將其標記為“離開環境”。標記“離開環境”的就回收記憶體。
- 工作流程:
- 垃圾回收器,在執行的時候會給儲存在記憶體中的所有變數都加上標記;
- 去掉環境中的變數以及被環境中的變數引用的變數的標記;
- 被加上標記的會被視為準備刪除的變數;
- 垃圾回收器完成記憶體清理工作,銷燬那些帶標記的值並回收他們所佔用的記憶體空間。
引用計數方式:
- 工作原理:跟蹤記錄每個值被引用的次數。
- 工作流程:
- 聲明瞭一個變數並將一個引用型別的值賦值給這個變數,這個引用型別值的引用次數就是 1;
- 同一個值又被賦值給另一個變數,這個引用型別值的引用次數加 1;
- 當包含這個引用型別值的變數又被賦值成另一個值了,那麼這個引用型別值的引用次數減 1;
- 當引用次數變成 0 時,說明沒辦法訪問這個值了;
- 當垃圾收集器下一次執行時,它就會釋放引用次數是 0 的值所佔的記憶體。
防抖,節流是什麼
- 函式防抖(debounce),指的是短時間內多次觸發同一事件,只執行最後一次,或者只執行最開始的一次,中間的不執行
- 函式節流(throttle),指連續觸發事件但是在 n 秒中只執行一次函式。即 2n 秒內執行 2 次...
深拷貝和淺拷貝
-
淺拷貝:只是拷貝了基本型別的資料,而引用型別資料,複製後也是會發生引用,我們把這種拷貝叫做淺拷貝(淺複製) 淺拷貝只複製指向某個物件的指標,而不復制物件本身,新舊物件還是共享同一塊記憶體。
-
深拷貝:在堆中重新分配記憶體,並且把源物件所有屬性都進行新建拷貝,以保證深拷貝的物件的引用圖不包含任何原有物件或物件圖上的任何物件,拷貝後的物件與原來的物件是完全隔離,互不影響。
# HTTP狀態碼
狀態碼的類別:
| 類別 | 原因 | 描述 | | ------ | ----------------------- | ------------- | | 1xx | Informational(資訊性狀態碼) | 接受的請求正在處理 | | 2xx | Success(成功狀態碼) | 請求正常處理完畢 | | 3xx | Redirection(重定向狀態碼) | 需要進行附加操作一完成請求 | | 4xx | Client Error (客戶端錯誤狀態碼) | 伺服器無法處理請求 | | 5xx | Server Error(伺服器錯誤狀態碼) | 伺服器處理請求出錯 |
Http和Https區別
HTTP
的URL 以http:// 開頭,而HTTPS 的URL 以http:// 開頭HTTP
是不安全的,而 HTTPS 是安全的HTTP
標準埠是80 ,而 HTTPS 的標準埠是443在OSI
網路模型中,HTTP工作於應用層,而HTTPS 的安全傳輸機制工作在傳輸層HTTP
無法加密,而HTTPS 對傳輸的資料進行加密HTTP
無需證書,而HTTPS 需要CA機構wosign的頒發的SSL證書
GET 和 POST 的區別
從 http 協議的角度來說,GET 和 POST 它們都只是請求行中的第一個單詞,除了語義不同,其實沒有本質的區別。
之所以在實際開發中會產生各種區別,主要是因為瀏覽器的預設行為造成的。
受瀏覽器的影響,在實際開發中,GET 和 POST 有以下區別:
- 瀏覽器在傳送 GET 請求時,不會附帶請求體
- GET 請求的傳遞資訊量有限,適合傳遞少量資料;POST 請求的傳遞資訊量是沒有限制的,適合傳輸大量資料。
- GET 請求只能傳遞 ASCII 資料,遇到非 ASCII 資料需要進行編碼;POST 請求沒有限制
- 大部分 GET 請求傳遞的資料都附帶在 path 引數中,能夠通過分享地址完整的重現頁面,但同時也暴露了資料,若有敏感資料傳遞,不應該使用 GET 請求,至少不應該放到 path 中
- 重新整理頁面時,若當前的頁面是通過 POST 請求得到的,則瀏覽器會提示使用者是否重新提交。若是 GET 請求得到的頁面則沒有提示。
- GET 請求的地址可以被儲存為瀏覽器書籤,POST 不可以
瀏覽器渲染機制、重繪、重排
網頁生成過程:
HTML
被HTML解析器解析成DOM
樹css
則被css解析器解析成CSSOM
樹- 結合
DOM
樹和CSSOM
樹,生成一棵渲染樹(Render Tree
) - 生成佈局(
flow
),即將所有渲染樹的所有節點進行平面合成 - 將佈局繪製(
paint
)在螢幕上
重排(也稱迴流): 當DOM的變化影響了元素的幾何屬性(DOM物件的位置和尺寸大小),瀏覽器需要重新計算元素的幾何屬性,將其安放在介面中正確的位置,這個過程就叫回流。觸發:
- 新增或者刪除可見的DOM元素
- 元素尺寸改變——邊距、填充、邊框、寬度和高度
重繪: 當一個元素的外觀發生了改變,但沒有改變佈局,重新把元素外觀繪製出來的過程,叫做重繪,觸發:
- 改變元素的color、background、box-shadow屬性
url按下回車之後發生了什麼
js
1 解析域名
2 快取判斷 --有資源直接返回、否則向伺服器發起新的請求
3 DNS解析
4 獲取MAC地址
5 會把請求的內容儲存到dns
6 TCP三次握手
7 HTTPS握手
8 返回資料
9 TCP四次揮手
cookie、sessionStorage、localStorage的區別
- cookie 可以設定失效時間
- localStorage 除非手動清除,否則永久儲存
- sessionStorage 盡在當前網頁有效,關閉頁面就被清除
- cookie儲存大小是4k,localStorage和sessionStorage是5M
- 請求時:cookie自動攜帶HTTP頭部中,localStorage和sessionStorage僅在瀏覽器儲存,不參與伺服器通訊
同源策略
瀏覽器有一個重要的安全策略,稱之為同源策略
其中,協議、埠號、域名必須一致,,稱之為同源,兩個源不同,稱之為跨源或跨域
同源策略是指,若頁面的源和頁面執行過程中載入的源不一致時,出於安全考慮,瀏覽器會對跨域的資源訪問進行一些限制
如何解決跨越問題
jsonp
(利用script
標籤沒有跨域限制的漏洞實現。缺點:只支援GET
請求)CORS
(設定Access-Control-Allow-Origin
:指定可訪問資源的域名Node
中介軟體代理Nginx
反向代理
談談你對 TCP 三次握手和四次揮手的理解
TCP 協議通過三次握手建立可靠的點對點連線,具體過程是:
首先伺服器進入監聽狀態,然後即可處理連線 1. 第一次握手:建立連線時,客戶端傳送 syn 包到伺服器,並進入 SYN_SENT 狀態,等待伺服器確認。在傳送的包中還會包含一個初始序列號 seq。此次握手的含義是客戶端希望與伺服器建立連線。 1. 第二次握手:伺服器收到 syn 包,然後迴應給客戶端一個 SYN+ACK 包,此時伺服器進入 SYN_RCVD 狀態。此次握手的含義是服務端迴應客戶端,表示已收到並同意客戶端的連線請求。
- 第三次握手:客戶端收到伺服器的 SYN 包後,向伺服器再次傳送 ACK 包,並進入 ESTAB_LISHED 狀態。
最後,服務端收到客戶端的 ACK 包,於是也進入 ESTAB_LISHED 狀態,至此,連線建立完成
當需要關閉連線時,需要進行四次揮手才能關閉
-
Client 向 Server 傳送 FIN 包,表示 Client 主動要關閉連線,然後進入 FIN_WAIT_1 狀態,等待 Server 返回 ACK 包。此後 Client 不能再向 Server 傳送資料,但能讀取資料。
-
Server 收到 FIN 包後向 Client 傳送 ACK 包,然後進入 CLOSE_WAIT 狀態,此後 Server 不能再讀取資料,但可以繼續向 Client 傳送資料。
- Client 收到 Server 返回的 ACK 包後進入 FIN_WAIT_2 狀態,等待 Server 傳送 FIN 包。
- Server 完成資料的傳送後,將 FIN 包傳送給 Client,然後進入 LAST_ACK 狀態,等待 Client 返回 ACK 包,此後 Server 既不能讀取資料,也不能傳送資料。
- Client 收到 FIN 包後向 Server 傳送 ACK 包,然後進入 TIME_WAIT 狀態,接著等待足夠長的時間(2MSL)以確保 Server 接收到 ACK 包,最後回到 CLOSED 狀態,釋放網路資源。
- Server 收到 Client 返回的 ACK 包後便回到 CLOSED 狀態,釋放網路資源。