一點感悟:當走完所有大廠的實習面試後

hello等風來發表於2018-08-09

七月雖然不是一個豐收的季節,但卻是一個十分酷熱的月份。不知有多少小夥伴跟我一樣,頂著大太陽奔波在各種面試的征途中。面試是一個漫長的過程。但是也是一個讓你快速提升的過程。其中包含了無數的血與淚。去面試前首先我們必須有牢固的基礎知識,足夠豐富的專案經歷(就我而言差不多是三個完整專案經歷,時間累計差不多接近一年)。然後就是表述能力,你要能把你的答案給面試官描述清楚,注意專業詞彙,這將大大提高面試官對你的印象分!

前言

學而不思則罔,思而不學則殆。當走完基本所有大廠之後,發現其實每個公司對基礎能力的考察都比較注重,只有基礎掌握好了,把前端所有的知識能夠一連串的理清。那麼不管面試題是什麼,都可以遊刃有餘的去回答。這裡就是把我所有面試過的問題的一些底層原理闡述,並不會去描述我在面試中碰到的題目。這樣一方面可以幫你過一遍js的基礎也可以幫助我加深理解。下面我就分模組的去講解沒一個知識點。篇幅過長,請耐心閱讀!!!

一、CSS面試篇

1、盒子模型

css中的盒子模型包括IE盒子模型和標準的W3C盒子模型。其盒子模型還是要歸宗於box-sizing的屬性,盒子模型對應的分被為border-box,content-box。所謂的標準盒子模型(border-box):width = 左右border+左右padding+contentwidth,而我們的IE盒子模型(border-box): width = content+padding+border 元素指定的任何內邊距和邊框都將在已設定的寬度和高度內進行繪製。

2、前端一畫素問題(畫一條0.5px的線)

方法一:transform:scaleY(0.5)使用偽元素設定1px的邊框,然後對邊框進行縮放(scaleY) 實現思路:

  • 1、設定目標元素的參考位置
  • 2、給目標元素新增一個偽元素before或者after,並設定絕對定位
  • 3、給偽元素新增1px的邊框
  • 4、用box-sizing: border-box 屬性把邊框都包進寬和高裡面
  • 5、寬和高設定為 200%
  • 6、整個盒子模型縮小為0.5
  • 7、調整盒子模型的位置,以左上角為基準 transform-origin: 0

方法二: border-image 設定圖片的邊框

3、transition和animation的區別

Animation和transition大部分屬性是相同的,他們都是隨時間改變元素的屬性值,他們的主要區別是transition需要觸發一個事件才能改變屬性, 而animation不需要觸發任何事件的情況下才會隨時間改變屬性值,並且transition為2幀,從from .... to,而animation可以一幀一幀的。

4、不定高的DIV居中

1.使用flex

在父盒子設定display: flex; justify-content: center;align-items: center
複製程式碼

2.使用css的transform

父盒子設定:display:relative
	Div 設定: transform: translate(-50%,-50%);position: absolute;top: 50%;left: 50%;
複製程式碼

3.display:table-cell

父盒子設定:display:table-cell; text-align:center;vertical-align:middle;
	Div 設定: display:inline-block;vertical-align:middle;
複製程式碼

5、浮動相應連結

  • 特性:浮動元素影響的不僅是自己,他會影響周圍元素對其進行環繞
  • 為什麼要清除浮動?(解決父元素高度坍陷問題) 一個塊級元素如果沒有設定height,其height由子元素撐開,對子元素使用了浮動之後,子元素就會脫離文件流也就是說,父及元素中沒有內容可以撐開其高度,這樣父級元素height就會被忽略。這就是所謂的高度坍塌
  • 如何清除浮動
1.給父級元素定義高度 
2.讓父級元素也浮動 
3.父級定義display:table 
4.父元素設定overflow:hidden 
5.clearfix:使用內容生成的方式清除浮動
	.clearfix:after {  // :after選擇器向選定的元素之後插入內容
   		    content:""; // 生成內容為空
   		    display: block; // 塊級元素顯示
   		    clear:both; // 清除前面元素
	}
不破壞文件流,沒有副作用
複製程式碼

6、css選擇器分類

基本的:
	1.id選擇器(id="name")
	2.類選擇器(class="head")
	3.標籤選擇器(body, div, ul, li)
	4.全域性選擇器(*)
複雜的:
	1.組合選擇器(.head .head_logo)
	2.後代選擇器 (#head .nav ul li 從父集到子孫集)
	3.群組選擇器 (div, span, img {color:Red} 具有相同樣式的標籤分組顯示)
	4.繼承選擇器
	5.偽類選擇器(連結樣式,a元素的偽類)
	6.子選擇器(div>p, 帶大於號>)
	7.CSS相鄰相鄰兄弟選擇器(h1+p, 帶加號+)
複製程式碼

優先順序:

不同級別:總結排序:!important > 行內樣式 > ID選擇器 > 類選擇器 > 標籤 > 萬用字元 > 繼承 > 瀏覽器預設屬性

  • 1.屬性後面加!import 會覆蓋頁面內任何位置定義的元素樣式
  • 2.作為style屬性寫在元素內的樣式
  • 3.id選擇器
  • 4.類選擇器
  • 5.標籤選擇器
  • 6.萬用字元選擇器(*)
  • 7.瀏覽器自定義或繼承

同一級別:後寫的會覆蓋先寫的

css選擇器的解析原則:選擇器定位DOM元素是從右往左的方向,這樣可以儘早的過濾掉一些不必要的樣式規則和元素

7、行內元素和塊元素

塊元素 行內元素
塊元素會獨佔一行,預設情況下,其寬度自動填滿父元素寬度 行元素不會佔據一行,會一直排在一行,直到一行排不下 行元素沒有寬度和高度屬性,塊級元素即使設定了寬度,還是會獨佔一行
塊級元素: div p forn ul li h1-h6 行內元素:span img input a i

注意:對於行內元素,font-size指定 他們的content area的高度,由於inline box = 上下的helf-leading,如果leading為0,在這種情況下,font-size指定了inline box的高度font-size指的是字型的高度,但是不能指定每個字形給定字型高度下的實際高度,導致了span的高度大於line-height

8、如何畫一個三角形

設定寬高,然後用border去畫
  		width: 0;
        	height: 0;
        	border-bottom: 100px solid cyan;
        	border-left: 50px solid transparent;
        	border-right: 50px solid transparent;
複製程式碼

9、使元素消失的方法

visibility:hidden、display:none、z-index=-1、opacity:0

  • 1.opacity:0,該元素隱藏起來了,但不會改變頁面佈局,並且,如果該元素已經繫結了一些事件,如click事件也能觸發
  • 2.visibility:hidden,該元素隱藏起來了,但不會改變頁面佈局,但是不會觸發該元素已經繫結的事件
  • 3.display:node, 把元素隱藏起來,並且會改變頁面佈局,可以理解成在頁面中把該元素刪掉

10、為什麼css放在頂部而js寫在後面

  • 1.瀏覽器預先載入css後,可以不必等待HTML載入完畢就可以渲染頁面了
  • 2.其實HTML渲染並不會等到完全載入完在渲染頁面,而是一邊解析DOM一邊渲染。
  • 3.js寫在尾部,主要是因為js主要扮演事件處理的功能,一方面很多操作是在頁面渲染後才執行的。另一方面可以節省載入時間,使頁面能夠更加的載入,提高使用者的良好體驗

但是隨著JS技術的發展,JS也開始承擔頁面渲染的工作。比如我們的UI其實可以分被對待,把渲染頁面的js放在前面,時間處理的js放在後面

二、佈局面試

1、flex彈性佈局

可以簡單的使一個元素居中(包括水平和垂直居中)柵格式系統佈局,bootstrap grid

2、三欄是佈局

三欄是佈局(兩邊兩欄寬度固定,中間欄寬度自適應)

  • 方案一:position(絕對定位法) center的div需要放在最後面 絕對定位法原理將左右兩邊使用absolute定位,因為絕對定位使其脫離文件流,後面的center會自然流動到他們的上賣弄,然後margin屬性,留出左右兩邊的寬度。就可以自適應了。
  • 方案二:float 自身浮動法 center的div需要放到後面 自身浮動法的原理就是對左右使用float:left和float:right,float使左右兩個元素脫離文件流,中間的正常文件流中,使用margin指定左右外邊距對其進行一個定位。
  • 方案三(聖盃佈局):原理就是margin負值法。使用聖盃佈局首先需要在center元素外部包含一個div,包含的div需要設定float屬性使其形成一個BFC,並且這個寬度和margin的負值進行匹配

3、左邊定寬,右邊自適應

  • 方案一:左邊設定浮動,右邊寬度設定100% .left{float:left} .right:{width:100%}
  • 方案二:左設定浮動,右用cacl去補寬度計算 .left{float:left} .right:{width:cacl(100vw-200px}
  • 方案三:父容器設定display:flex right部分是設定flex:1
  • 方案四:右邊div套個包裹、並前置、左及包裹 雙浮動

4、水平居中

行內元素居中(父元素text-align:center)
	塊狀元素居中(塊狀元素沒發用text-align)
		1.寬度一定:margin:auto
		2.寬度不定:塊級變行內,然後在父上text-aligin
複製程式碼

5、BFC

理解:BFC是css佈局的一個概念,是一塊獨立的渲染區域,一個環境,裡面的元素不會影響到外部的元素
如何生成BFC:(脫離文件流)
	     【1】根元素,即HTML元素(最大的一個BFC)
	     【2】float的值不為none
	     【3】position的值為absolute或fixed
	     【4】overflow的值不為visible(預設值。內容不會被修剪,會呈現在元素框之外)
	     【5】display的值為inline-block、table-cell、table-caption
BFC佈局規則:1.內部的Box會在垂直方向,一個接一個地放置。
	     2.屬於同一個BFC的兩個相鄰的Box的margin會發生重疊
	     3.BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素。反之也如此, 文字環繞效果,設定float
	     4.BFC的區域不會與float box重疊。
	     5.計算BFC的高度,浮動元素也參與計算
BFC作用:1.自適應兩欄佈局
	 2.可以阻止元素被浮動元素覆蓋
	 3.可以包含浮動元素---清除內部浮動 原理::觸發父div的BFC屬性,使下面的子div都處在父div的同一個BFC區域之內
	 4.分屬於不同的BFC時,可以阻止margin重疊
複製程式碼

三、js面試篇

1、前端事件流

事件流描述的是從頁面中接受事件的順序,可以分為:事件捕獲階段 處於目標階段 事件冒泡階段其中需要主要的是addeventListener這個函式 最後這個布林值引數如果是true,表示在捕獲階段呼叫事件處理程式;如果是false,表示在冒泡階段呼叫事件處理程式。

  • 1、事件捕獲階段:實際目標div在捕獲階段不會接受事件,也就是在捕獲階段,事件從document到再到就停止了
  • 2、處於目標階段:事件在div發生並處理,但是事件處理會被看成是冒泡階段的一部分。
  • 3、冒泡階段:事件又傳播迴文件
阻止冒泡事件event.stopPropagation()
 		  function stopBubble(e) {
   		if (e && e.stopPropagation) { // 如果提供了事件物件event 這說明不是IE瀏覽器
  		e.stopPropagation()
    		} else {
  		window.event.cancelBubble = true //IE方式阻止冒泡
    	      }
  		   }
阻止預設行為event.preventDefault()
	 function stopDefault(e) {
	    if (e && e.preventDefault) {
         e.preventDefault()
        } else {
            // IE瀏覽器阻止函式器預設動作的行為
            window.event.returnValue = false
        }
    }
複製程式碼

事件如何先捕獲後冒泡:

在DOM標準事件模型中,是先捕獲後冒泡。但是如果要實現先冒泡後捕獲的效果,對於同一個事件,監聽捕獲和冒泡,分別對應相應的處理函式,監聽到捕獲事件,先暫緩執行,直到冒泡事件被捕獲後再執行捕獲事件。

哪些事件不支援冒泡事件:

滑鼠事件:mouserleave  mouseenter
焦點事件:blur focus
UI事件:scroll resize
複製程式碼

2、事件委託(提高效能)

簡介:事件委託指的是,不在事件的(直接dom)上設定監聽函式,而是在其父元素上設定監聽函式。通過事件冒泡,父元素可以監聽到子元素上事件的觸發通過判斷事件發生元素DOM的型別,來做出不同的響應。

  • 舉例子: 最經典的就是ui和li標籤的事件監聽,比如我們在新增事件的時候,採用事件委託機制,不會在li標籤上直接新增,而是在ul父元素上新增
  • 好處:可以比較合適動態元素的繫結,新新增的子元素也會監聽函式,也可以有事件觸發機制

3、js的new操作符做了什麼

new操作符建立了一個空物件,這個物件原型指向建構函式的prototype,執行建構函式後返回這個物件。如果不要父類的屬性跟方法,在函式的prototype上去new這個父類。

4、this的指向

  • 1、當函式作為物件的方法被呼叫時,this就會指向該物件。
  • 2、作為普通函式,this指向window。
  • 3、構造器呼叫,this指向返回的這個物件。
  • 4、箭頭函式 箭頭函式的this繫結看的是this所在函式定義在哪個物件下,就繫結哪個物件。如果有巢狀的情況,則this繫結到最近的一層物件上

4.1、箭頭函式this的原理:

this指向的固定化,並不是因為箭頭函式內部有繫結this的機制,實際原因是箭頭函式根本沒有自己的this,導致內部的this就是外層程式碼塊的this。正是因為它沒有this,所以也就不能用作建構函式。

4.2、怎麼改變this的指向呢?

1.使用es6的箭頭函式;2.在函式內部使用that = this;3.使用apply,call,bind; 4.new例項化一個物件

4.3、bind,apply,call的區別

通過apply和call改變函式的this指向,他們兩個函式的第一個引數都是一樣的表示要改變指向的那個物件,第二個引數,apply是陣列,而call則是arg1,arg2...這種形式。bind一個是返回一個函式,並不會立即執行第二個是帶引數(第一個引數要指向的this,後面的的引數用來傳遞

5、深淺拷貝參考連結

基本型別 引用型別
基本型別:undefined,null,Boolean,String,Number,Symbol在記憶體中佔據固定大小,儲存在棧記憶體中 引用型別:Object,Array,Date,Function,RegExp等 引用型別的值是物件 儲存在堆記憶體中,棧記憶體儲存的是物件的變數識別符號以及物件在堆記憶體中的儲存地址。
基本型別的複製:其實就是建立了一個新的副本給將這個值賦值給新變數, 改變值舊物件不會改變 引用型別的複製:其實就是複製了指標,這個最終都將指向同一個物件,改變其值新物件也會改變

注意:基本型別的比較 == 會進行型別轉換

淺拷貝 深拷貝
僅僅就是複製了引用,彼此操作不影響,slice() concat() object.assign 在堆中重新分配記憶體,不同的地址,相同的值,互不影響的 JSON.parse()將一個js物件序列化為一個json字串JSON.stringify()將json字串反序列化為一個js物件 es6的展開 {...}
重新在堆疊中建立記憶體,拷貝前後物件的基本型別互不影響。只拷貝一層,不能對物件進行子物件進行拷貝 對物件中的子物件進行遞迴拷貝,拷貝前後兩個物件互不影響

6、setTimeout和setInterval的機制

因為js是單執行緒的。瀏覽器遇到etTimeout和setInterval會先執行完當前的程式碼塊,在此之前會把定時器推入瀏覽器的待執行時間佇列裡面,等到瀏覽器執行完當前程式碼之後會看下事件佇列裡有沒有任務,有的話才執行定時器裡的程式碼

7、前端跨域問題

同源策略(協議+埠號+域名要相同)

  • 1、jsonp跨域(只能解決get) 原理:動態建立一個script標籤。利用script標籤的src屬性不受同源策略限制,因為所有的src屬性和href屬性都不受同源策略的限制,可以請求第三方伺服器資源內容
	步驟:1.去建立一個script標籤
		      2.script的src屬性設定介面地址
		      3.介面引數,必須要帶一個自定義函式名,要不然後臺無法返回資料
		      4.通過定義函式名去接受返回的資料    	
複製程式碼
  • 2、document.domain 基礎域名相同 子域名不同
  • 3、window.name 利用在一個瀏覽器視窗內,載入所有的域名都是共享一個window.name
  • 4、伺服器設定對CORS的支援 原理:伺服器設定Access-Control-Allow-Origin HTTP響應頭之後,瀏覽器將會允許跨域請求
  • 利用h5新特性window.postMessage()
iframe元素建立包含另外一個文件的內聯框架(行內框架)(setTimeout進行非同步載入)
      解釋:瀏覽器中的瀏覽器!用於設定文字或者圖形的浮動圖文框或容器
      它和跨域
        1、document.domain 實現主域名相同,子域名不同的網頁通訊
          都設定為超域:document.domain = 'demo.com'
        2、window.postMessageht(data, url),h5的API,啟動跨域通訊
複製程式碼

8、圖片預載入和懶載入

8.1、預載入:

提前載入圖片,當使用者需要檢視是可以直接從本地快取中渲染

為什麼要使用預載入:在網頁載入之前,對一些主要內容進行載入,以提供使用者更好的體驗,減少等待時間。否則,如果一個頁面的內容過於龐大,會出現留白。

解決頁面留白的方案: 1.預載入

2.使用svg站點陣圖片,將一些結構快速搭建起來,等待請求的資料來了之後,替換當前的佔位符

實現預載入的方法:

		1.使用html標籤
		2.使用Image物件
		3.使用XMLHTTPRequest對像,但會精細控制預載入過程
複製程式碼

8.2、懶載入(lazyload)

客戶端優化,減少請求數和延遲請求數,提升使用者體驗,減少無效資源的載入,防止併發載入的資源過多會阻塞js的載入,影響網站的正常使用

原理:首先將頁面上的圖片的src屬性設定為空字串,而圖片的真是路經則設定帶data-original屬性中,當頁面滾動的時候需要去監聽scroll事件,在scroll事件的回撥中,判斷我們的懶載入的圖片是否進入到可視區域,如果圖片在可視區域將圖片的src屬性設定為data-original的值,這樣就可以實現延遲載入。

9、函式節流和防抖

防抖 節流
短時間內多次觸發同一個事件,只執行最後一次,或者在開始時執行,中間不執行。比如公交車上車,要等待最後一個乘客上車 節流是連續觸發事件的過程中以一定時間間隔執行函式。節流會稀釋你的執行頻率,比如每間隔1秒鐘,只會執行一次函式,無論這1秒鐘內觸發了多少次事件

都為解決高頻事件而來, scroll mousewhell mousemover touchmove onresize,後面有相應的程式碼實現函式的節流和防抖。

10、js垃圾回收機制

1.JS具有自動垃圾收集的機制
2.JS的記憶體生命週期(變數的生命)
	1.分配你所需要的空間 var a = 20
	2.使用分配帶的記憶體(讀寫) alert(a + 10)
	3.不適用的時候,釋放記憶體空間 a = null 
3.JS的垃圾收集器每隔固定的時間就執行一次釋放操作,通用的是通過標記清除的演算法
4.在區域性作用域中,垃圾回收器很容易做出判斷並回收,全域性比較難,因此應避免全域性變數

   標記清除演算法:js最常見的垃圾回收方式,當變數進入執行環境的時候,比如函式中宣告一個變數,垃圾回收器將他標記為'進入環境',
		 當變數離開(函式執行完後),就其標記為'離開環境'。垃圾回收器會在執行的時候給儲存在記憶體中的所有變數加上標記,
		 然後去掉環境中的變數以及被環境中該變數所引用的變數(閉包)。在這些完成之後仍存在標記的就是要刪除的變數了
複製程式碼

11、一些檢驗方法

千萬不要使用typeof來判斷物件和陣列,因為這種型別都會返回object。

  • typeOf()是判斷基本型別的Boolean,Number,symbol, undefined, String。 對於引用型別:除function,都返回object null返回object。
  • installOf() 用來判斷A是否是B的例項,installof檢查的是原型。
  • toString() 是Object的原型方法,對於 Object 物件,直接呼叫 toString() 就能返回 [Object Object] 。而對於其他物件,則需要通過 call / apply 來呼叫才能返回正確的型別資訊。
  • hasOwnProperty()方法返回一個布林值,指示物件自身屬性中是否具有指定的屬性,該方法會忽略掉那些從原型鏈上繼承到的屬性。
  • isProperty()方法測試一個物件是否存在另一個物件的原型鏈上。
  • valueof:所有物件都有valueof,如果存在任意原始值,他就預設將物件轉化為表示它的原始值。如果物件是複合值,而卻大部分物件無法真正表示一個原始值,因此預設的valueof()方法簡單的返回物件本身,而不是返回原始值

12、splice和slice、map和forEach、 filter()、reduce()的區別

 1.slice(start,end):方法可以從已有陣列中返回選定的元素,返回一個新陣列,包含從start到end(不包含該元素)的陣列方法
	注意:該方法不會更新原陣列,而是返回一個子陣列
 2.splice():該方法想或者從陣列中新增或刪除專案,返回被刪除的專案。(該方法會改變原陣列)
	splice(index, howmany,item1,...itemx)
		·index引數:必須,整數規定新增或刪除的位置,使用負數,從陣列尾部規定位置
		·howmany引數:必須,要刪除的數量,
		·item1..itemx:可選,向陣列新增新專案
3.map():會返回一個全新的陣列。使用於改變資料值的時候。會分配記憶體儲存空間陣列並返回,forEach()不會返回資料
4.forEach(): 不會返回任何有價值的東西,並且不打算改變資料,單純的只是想用資料做一些事情,他允許callback更改原始陣列的元素
5.reduce(): 方法接收一個函式作為累加器,陣列中的每一個值(從左到右)開始縮減,最終計算一個值,不會改變原陣列的值
6.filter(): 方法建立一個新陣列,新陣列中的元素是通過檢查指定陣列中符合條件的所有元素。它裡面通過function去做處理	
複製程式碼

13、js\css阻塞

js阻塞 css阻塞
所有瀏覽器在下載JS的時候,會阻止一切其他活動,比如其他資源的下載,內容的呈現等等。直到JS下載、解析、執行完畢後才開始繼續並行下載其他資源並呈現內容。為了提高使用者體驗,新一代瀏覽器都支援並行下載JS,但是JS下載仍然會阻塞其它資源的下載(例如.圖片,css檔案等)。 因為瀏覽器會維持html中css和js的順序,樣式表必須在嵌入的JS執行前先載入、解析完。而嵌入的JS會阻塞後面的資源載入,所以就會出現上面CSS阻塞下載的情況。

14、類的建立和繼承

(es6)中class, extends

14.1、 繼承:

  • 原型鏈繼承: function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; 無法實現多繼承
  • 構造繼承:使用父類的建構函式來增強子類例項。function Cat(name){Animal.call(this);this.name = name || 'Tom';} 無法繼承父類原型鏈上的屬性跟方法 installof去檢驗
  • 例項繼承:為父類例項新增新特性,作為子類例項的返回
  • 拷貝繼承:拷貝父類元素上的屬性跟方法
  • 組合繼承:構造繼承 + 原型繼承的組合體
  • 寄生組合繼承:通過寄生方式,在構造繼承上加一個Super函式(沒有例項和方法) 讓他的原型鏈指向父類的原型鏈 砍掉父類的例項屬性,這樣,在呼叫兩次父類的構造的時候,就不會初始化兩次例項方法/屬性

14.2 給兩個建構函式A和B,如何實現A繼承B (Object.prototype)

	function A(....){} A.prototype...
	function B(....){} B.prototype...
	A.prototype = Object.create(B.prototype)  再A的建構函式裡new B(props)		
	
   使用new一個函式的話,函式裡的建構函式的引數就為undefined,裡面的一些函式可能執行錯誤,因為this改變了	
	Object.create =  function (o) {
		var F = function () {};
		F.prototype = o;
		return new F();
		};
複製程式碼

15、閉包和原型

15.1、閉包的理解

  • 1、內部函式可以訪問定義他們外部函式的引數和變數。(作用域鏈的向上查詢,把外圍的作用域中的變數值儲存在記憶體中而不是在函式呼叫完畢後銷燬)設計私有的方法和變數,避免全域性變數的汙染
  • 2、函式巢狀函式
  • 3、本質是將函式內部和外部連線起來。優點是可以讀取函式內部的變數,讓這些變數的值始終儲存在記憶體中,不會在函式被呼叫之後自動清除

15.2、閉包的缺陷:

1.閉包的缺點就是常駐記憶體會增大記憶體使用量,並且使用不當容易造成記憶體洩漏
2.如果不是因為某些特殊任務而需要閉包,在沒有必要的情況下,在其它函式中建立函式是不明智的,因為閉包對指令碼效能具有負面影響,包括處理速度和記憶體消耗。   
複製程式碼

15.3、記憶體的理解

記憶體溢位和記憶體洩漏(給的不夠用| 用了不歸還)

  • 1、記憶體溢位:在程式中申請記憶體時,沒有足夠的記憶體空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是記憶體溢位
  • 2、記憶體洩漏:在程式申請記憶體後,無法釋放已申請的記憶體空間,一次記憶體洩漏危害可以忽略,但記憶體洩漏堆積後果很嚴重,無論多少記憶體,遲到會被佔光 舉列子:閉包中的this,物件函式。匿名函式返回函式return function

15.4、作用域

作用域:(由當前環境與上層環境一系列的變數物件組成!!!保證當先執行環境裡,有權訪問的變數和函式是有序的,作用域鏈變數只能被向上訪問)

定義:由當前環境與上層環境的一系列變數物件組成(函式巢狀函式,內部一級級往上有序訪問變數或物件)

作用是:保證當前執行環境裡,有權訪問的變數和函式時有序的,作用域鏈的變數只能被向上訪問 變數訪問到window物件及被終止,作用域鏈向下訪問是不允許的 1.改變作用域有 with try..中的catch, 2.所有為定義的直接賦值的變數自動宣告為全域性作用域

作用域:一套規則,管理引擎如何在當前作用域以及巢狀的子作用域中根據識別符號名稱
	查詢變數(識別符號就是變數或者函式名)(只用全域性作用域和區域性作用域)(作用域在它建立的時候就存在了)

程式碼執行分為兩個階段:
	1.程式碼編譯階段:有編譯器完成,將程式碼翻譯可執行的程式碼,這個階段會被確定
	2.程式碼執行階段:有js引擎完成,主要執行可執行的大媽,這個階段執行上下文被建立(物件被建立)

執行上下文:一個看不見得物件,存在若干個屬性和變數,它被呼叫的時候建立的。函式被呼叫檢視的this指向的object,object就是上下文(只有被呼叫的時候建立)
複製程式碼

15.5、作用域鏈參考連結

    · 當程式碼在一個環境中執行時,會建立變數物件的一個作用域鏈,
	舉例子:var name ="Tom"
		function sayHi () {
		    alert('Hi,'+name)
		}
		sayHi()  //Hi, Tom
	函式sayHi()的執行環境為全域性環境,所以它的變數物件為window。當函式執行到name時,先查詢區域性環境,找到則換回,否則順著作用域查詢,在全域性環境中,
	找到name返回,這一查詢變數的有序過程的依據就是作用域。

    · 作用域鏈是保證執行環境有權訪問的所有變數和函式的有序訪問
複製程式碼

15.6、原型鏈

原型鏈:函式的原型鏈物件constructor預設指向函式本身,原型物件除了有原型屬性外,為了實現繼承,還有一個原型鏈指標_proto_,該指標是指向上一層的原型物件,而上一層的原型物件的結構依然類似。因此可以利用_proto_一直指向Object的原型物件上,而Object原型物件用Object.prototype.proto=null表示原型鏈頂端。如此形成了js的原型鏈繼承。同時所有的js物件都有Object的基本防範

四、伺服器端面試篇

1、狀態碼

2XX(成功處理了請求狀態)
          200 伺服器已經成功處理請求,並提供了請求的網頁
          201 使用者新建或修改資料成功
          202 一個請求已經進入後臺
          204 使用者刪除成功
3XX(每次請求使用的重定向不要超過5次)
          304 網頁上次請求沒有更新,節省頻寬和開銷
4XX(表示請求可能出錯,妨礙了伺服器的處理)
          400 伺服器不理解請求的語法
          401 使用者沒有許可權(使用者名稱,密碼輸入錯誤)
          403 使用者得到授權(401相反),但是訪問被禁止
          404 伺服器找不到請求的網頁,
5XX(表示伺服器在處理請求的時候發生內部錯誤)
          500 伺服器遇到錯誤,無法完成請求
          503 伺服器目前無法使用(超載或停機維護)
複製程式碼

2、304的快取原理(新增Etag標籤.last-modified)

  • 1.伺服器首先產生Etag,伺服器可在稍後使用它來判斷頁面是否被修改。本質上,客戶端通過該記號傳回伺服器要求伺服器驗證(客戶端)快取)
  • 2.304是HTTP的狀態碼,伺服器用來標識這個檔案沒有被修改,不返回內容,瀏覽器接受到這個狀態碼會去去找瀏覽器快取的檔案
  • 3.流程:客戶端請求一個頁面A。伺服器返回頁面A,並在A上加一個Tage客服端渲染該頁面,並把Tage也儲存在快取中。客戶端再次請求頁面A並將上次請求的資源和ETage一起傳遞給伺服器。伺服器檢查Tage.並且判斷出該頁面自上次客戶端請求之後未被修改。直接返回304

last-modified: 客服端請求資源,同時有一個last-modified的屬性標記此檔案在伺服器最後修改的時間,客服端第二次請求此url時,根據http協議。瀏覽器會向伺服器傳送一個If-Modified-Since報頭,詢問該事件之後檔案是否被修改,沒修改返回304

 有了Last-Modified,為什麼還要用ETag?
  1、因為如果在一秒鐘之內對一個檔案進行兩次更改,Last-Modified就會不正確(Last—Modified不能識別秒單位的修改)
  2、某些伺服器不能精確的得到檔案的最後修改時間
  3、一些檔案也行會週期新的更改,但是他的內容並不改變(僅僅改變修改的事件),這個時候我們並不希望客戶端認為檔案被修改,而重新Get

ETag,為什麼還要用Last-Modified?
  1、兩者互補,ETag的判斷的缺陷,比如一些圖片等靜態檔案的修改
  2、如果每次掃描內容都生成ETag比較,顯然要比直接比較修改時間慢的多。


ETag是被請求變數的實體值(檔案的索引節,大小和最後修改的時間的Hash值)
  1、ETag的值伺服器端對檔案的索引節,大小和最後的修改的事件進行Hash後得到的。
複製程式碼

3、get/post的區別

  • 1.get資料是存放在url之後,以?分割url和傳輸資料,引數之間以&相連; post方法是把提交的資料放在http包的Body中
  • 2.get提交的資料大小有限制,(因為瀏覽器對url的長度有限制),post的方法提交的資料沒有限制
  • 3.get需要request.queryString來獲取變數的值,而post方式通過request.from來獲取變數的值
  • 4.get的方法提交資料,會帶來安全問題,比如登入一個頁面,通過get的方式提交資料,使用者名稱和密碼就會出現在url上

4、http和https的總結

4.1、http協議的理解

1.超文字的傳輸協議,是用於從全球資訊網伺服器超文字傳輸到本地資源的傳輸協議
2.基於TCP/IP通訊協議來傳遞資料(HTML,圖片資源)
3.基於運用層的物件導向的協議,由於其簡潔、快速的方法、適用於分散式超媒體資訊系統
4.http請求資訊request:
	請求行(request line)、請求頭部(header),空行和請求資料四部分構成

	請求行,用來說明請求型別,要訪問的資源以及所使用的HTTP版本.
	請求頭部,用來說明伺服器要使用的附加資訊
	空行,請求頭部後面的空行是必須的
	請求資料也叫主體,可以新增任意的其他資料。
5.http相應資訊Response
	狀態行、訊息報頭、空行和響應正文

	狀態行,由HTTP協議版本號, 狀態碼, 狀態訊息 三部分組成
	訊息報頭,用來說明客戶端要使用的一些附加資訊
	空行,訊息報頭後面的空行是必須的
	響應正文,伺服器返回給客戶端的文字資訊。
複製程式碼

4.2、http和https的區別

http https
是以安全為目標的HTTP通道,簡單講是HTTP的安全版本,通過SSL加密 超文字傳輸協議。是一個客服端和伺服器端請求和應答的標準(tcp),使瀏覽器更加高效,使網路傳輸減少

4.3、http1.0、1.1、2.0的區別

1.0跟1.1的區別:

長連線:HTTP1.0需要使用keep-alive引數來告知伺服器建立一個長連線,而HTP1.1預設支援長連線

節約寬頻:HTTP1.1支援只傳送一個header資訊(不帶任何body資訊)

host域(設定虛擬站點,也就是說,webserver上的多個虛擬站點可以共享同一個ip埠):HTTP1.0沒有host域

1.1跟2.0的區別:

  • 1.http2採用的二進位制文字傳輸資料,而非http1文字格式,二進位制在協議的解析和擴充套件更好
  • 2.資料壓縮:對資訊頭採用了HPACK進行壓縮傳輸,節省了資訊頭帶來的網路流量
  • 3.多路複用:一個連線可以併發處理多個請求
  • 4.伺服器推送:我們對支援HTTP2.0的webserver請求資料的時候,伺服器會順便把一些客戶端需要的資源一起推送到客戶端,免得客戶端再次建立連線傳送請求到伺服器端獲取。這種方式非常合適載入靜態資源

5、web總結

5.1、web快取

1.web快取就是存在於客戶端與伺服器之間的一個副本、當你第一個發出請求後,快取根據請求儲存輸出內容的副本
2.快取的好處
        (1)減少不必要的請求
	(2)降低伺服器的壓力,減少伺服器的消耗
	(3)降低網路延遲,加快頁面開啟速度(直接讀取瀏覽器的數)
複製程式碼

5.2、常見的web安全及防護原理

  • 1.sql注入原理:通郭sql命令插入到web表單遞交或者輸入活命,達到欺騙伺服器執行的惡意sql命令 防範:1.對使用者輸入進行校驗 2.不適用動態拼接sql
  • 2.XSS(跨站指令碼攻擊):往web頁面插入惡意的html標籤或者js程式碼。 舉例子:在論壇放置一個看是安全的連結,竊取cookie中的使用者資訊 防範:1.儘量採用post而不使用get提交表單 2.避免cookie中洩漏使用者的隱式
  • 3.CSRF(跨站請求偽裝):通過偽裝來自受信任使用者的請求 舉例子:黃軼老師的webapp音樂請求資料就是利用CSRF跨站請求偽裝來獲取QQ音樂的資料 防範:在客服端頁面增加偽隨機數,通過驗證碼
  • XSS和CSRF的區別: 1.XSS是獲取資訊,不需要提前知道其他使用者頁面的程式碼和資料包 2.CSRF代替使用者完成指定的動作,需要知道其他頁面的程式碼和資料包

5.3、CDN(內容分發網路)

1.儘可能的避開網際網路有可能影響資料傳輸速度和穩定性的瓶頸和環節。使內容傳輸的更快更穩定。
2.關鍵技術:內容儲存和分發技術中
3.基本原理:廣泛採用各種快取伺服器,將這些快取伺服器分佈到使用者訪問相對的地區或者網路中。當使用者訪問網路時利用全域性負載技術
	    將使用者的訪問指向距離最近的快取伺服器,由快取伺服器直接相應使用者的請求(全域性負載技術)
複製程式碼

6、前端呈現流程(TCP三次握手,DOM樹渲染)

6.1、從輸入url到獲取頁面的完整過程 參考連結

1.查詢NDS(域名解析),獲取域名對應的IP地址  查詢瀏覽器快取
2.瀏覽器與伺服器建立tcp連結(三次握手)
3.瀏覽器向伺服器傳送http請求(請求和傳輸資料)
4.伺服器接受到這個請求後,根據路經引數,經過後端的一些處理生成html程式碼返回給瀏覽器
5.瀏覽器拿到完整的html頁面程式碼開始解析和渲染,如果遇到外部的css或者js,圖片一樣的步驟
6.瀏覽器根據拿到的資源對頁面進行渲染,把一個完整的頁面呈現出來
複製程式碼

6.2、TCP三次握手

客服端發c起請求連線伺服器端s確認,伺服器端也發起連線確認客服端確認。

  • 第一次握手:客服端傳送一個請求連線,伺服器端只能確認自己可以接受客服端傳送的報文段
  • 第二次握手: 服務端向客服端傳送一個連結,確認客服端收到自己傳送的報文段
  • 第三次握手: 伺服器端確認客服端收到了自己傳送的報文段

6.3、瀏覽器渲染原理及流程 DOM -> CSSOM -> render -> layout -> print

流程:解析html以及構建dom樹 -> 構建render樹 ->  佈局render樹 -> 繪製render樹
	概念:1.構建DOM樹: 渲染引擎解析HTML文件,首先將標籤轉換成DOM樹中的DOM node(包括js生成的標籤)生成內容樹
	      2.構建渲染樹: 解析對應的css樣式檔案資訊(包括js生成的樣式和外部的css)
	      3.佈局渲染樹:從根節點遞迴呼叫,計算每一個元素的大小,位置等。給出每個節點所在的螢幕的精準位置
	      4.繪製渲染樹:遍歷渲染樹,使用UI後端層來繪製每一個節點
   
	重繪:當盒子的位置、大小以及其他屬性,例如顏色、字型大小等到確定下來之後,瀏覽器便把這些顏色都按照各自的特性繪製一遍,將內容呈現在頁面上
		觸發重繪的條件:改變元素外觀屬性。如:color,background-color等
		重繪是指一個元素外觀的改變所觸發的瀏覽器行為,瀏覽器會根據元素的新屬性重新繪製,使元素呈現新的外觀
	注意:table及其內部元素需要多次計算才能確定好其在渲染樹中節點的屬性值,比同等元素要多發時間,要儘量避免使用table佈局
	
	重排(重構/迴流/reflow): 當渲染書中的一部分(或全部)因為元素的規模尺寸,佈局,隱藏等改變而需要重新構建,這就是迴流。
		每個頁面都需要一次迴流,就是頁面第一次渲染的時候
	重排一定會影響重繪,但是重繪不一定會影響重排
複製程式碼

7、前端儲存總結

7.1、儲存方式與傳輸方式

  • 1.indexBD: 是h5的本地儲存庫,把一些資料儲存到瀏覽器中,沒網路,瀏覽器可以從這裡讀取資料,離線運用。5m
  • 2.Cookie: 通過瀏覽器記錄資訊確認使用者身份,最大4kb,這也就限制了傳輸的資料,請求的效能會受到影響
  • 3.Session: 伺服器端使用的一種記錄客戶狀態的機制(session_id存在set_cookie傳送到客服端,儲存為cookie)
  • 4.localStroage: h5的本地儲存,資料永久儲存在客服端
    1、cookie,sessionStorage,localStorage是存放在客戶端,session物件資料是存放在伺服器上
       實際上瀏覽器和伺服器之間僅需傳遞session id即可,伺服器根據session-id找到對應的使用者session物件
        session儲存資料更安全一些,一般存放使用者資訊,瀏覽器只適合儲存一般的資料
    2、cookie資料始終在同源的http請求中攜帶,在瀏覽器和伺服器來回傳遞,裡面存放著session-id
       sessionStorage,localStorage僅在本地儲存
    3、大小限制區別,cookie資料不超過4kb,localStorage在谷歌瀏覽中2.6MB
    4、資料有效期不同,cookie在設定的(伺服器設定)有效期內有效,不管視窗和瀏覽器關閉
      sessionStorage僅在當前瀏覽器視窗關閉前有效,關閉即銷燬(臨時儲存)
      localStorage始終有效	
複製程式碼

7.2、SessionStorage和localStorage區別:

1.sessionStorage用於本地儲存一個會話(session)中的資料,這些資料只有在用一個會話的頁面中才能被訪問(也就是說在第一次通訊過程中)
   並且在會話結束後資料也隨之銷燬,不是一個持久的本地儲存,會話級別的儲存
2.localStorage用於持久化的本地儲存,除非主動刪除資料,否則不會過期
複製程式碼

7.3、token、cookie、session三者的理解

  • 1、token就是令牌,比如你授權(登入)一個程式時,他就是個依據,判斷你是否已經授權該軟體(最好的身份認證,安全性好,且是唯一的)使用者身份的驗證方式

  • 2、cookie是寫在客戶端一個txt檔案,裡面包括登入資訊之類的,這樣你下次在登入某個網站,就會自動呼叫cookie自動登入使用者名稱伺服器生成,傳送到瀏覽器、瀏覽器儲存,下次請求再次傳送給伺服器(存放著登入資訊)

  • 3、session是一類用來客戶端和伺服器之間儲存狀態的解決方案,會話完成被銷燬(代表的就是伺服器和客戶端的一次會話過程)cookie中存放著sessionID,請求會傳送這個id。sesion因為request物件而產生。

7.3、基於Token的身份驗證:(最簡單的token: uid使用者唯一的身份識別 + time當前事件戳 + sign簽名)

  1、使用者通過使用者名稱和密碼傳送請求
  2、伺服器端驗證
  3、伺服器端返回一個帶簽名的token,給客戶端
  4、客戶端儲存token,並且每次用於傳送請求
  5、伺服器驗證token並且返回資料
  每一次請求都需要token
 cookie與session區別
  1、cookie資料存放在客戶的瀏覽器上,session資料放在伺服器上。
  2、cookie不是很安全,別人可以分析存放在本地的COOKIE並進行COOKIE欺騙考慮到安全應當使用session。
  3、session會在一定時間內儲存在伺服器上。當訪問增多,會比較佔用你伺服器的效能考慮到減輕伺服器效能方面,應當使用COOKIE。
  4、單個cookie儲存的資料不能超過4K,很多瀏覽器都限制一個站點最多儲存20個cookie。
複製程式碼

7.4、session與token區別

  • 1、session認證只是把簡單的User的資訊儲存Session裡面,sessionID不可預測,一種認證手段。只存在服務端,不能共享到其他的網站和第三方App
  • 2、token是oAuth Token,提供的是認證和授權,認證針對使用者,授權是針對App,目的就是讓某APP有權訪問某使用者的的資訊。Token是唯一的,token不能轉移到其他的App,也不能轉到其他使用者上。(適用app)
  • 3、session的狀態是存在伺服器端的,客戶端只存在session id, Token狀態是儲存在客戶端的

7.5、Cookie的弊端有哪些???(優勢:儲存客戶端資料,分擔了伺服器儲存的負擔)

  1、數量和長度的限制。每個特定的域名下最多生成20個cookie(chorme和safari沒有限制)
  2、安全性問題。
複製程式碼

五、寫在後面

由於篇幅過長,我準備了一個txt文件,裡面有更多的前端基礎知識。包括這裡未曾談及的Vue,React,node,資料結構等。奉上我的文件地址前端面試武林祕籍,學習總是需要不斷的積累和總結的。寫此文的目的也很明確,若總結的不好地方歡迎指出並在下方評論,或者你認為很好的知識點,沒有歸納到,也希望能夠分享出來,幫助大家,也提高自己。

相關文章