您好,登錄后才能下訂單哦!
一、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相鄰相鄰兄弟選擇器(h2+p, 帶加號+)
復制代碼
優先級:
不同級別:總結排序:!important > 行內樣式 > ID選擇器 > 類選擇器 > 標簽 > 通配符 > 繼承 > 瀏覽器默認屬性
1.屬性后面加!import 會覆蓋頁面內任何位置定義的元素樣式
2.作為style屬性寫在元素內的樣式
3.id選擇器
4.類選擇器
5.標簽選擇器
6.通配符選擇器(*)
7.瀏覽器自定義或繼承
同一級別:后寫的會覆蓋先寫的
css選擇器的解析原則:選擇器定位DOM元素是從右往左的方向,這樣可以盡早的過濾掉一些不必要的樣式規則和元素
7、行內元素和塊元素
塊元素
行內元素
塊元素會獨占一行,默認情況下,其寬度自動填滿父元素寬度 行元素不會占據一行,會一直排在一行,直到一行排不下
行元素沒有寬度和高度屬性,塊級元素即使設置了寬度,還是會獨占一行
塊級元素: div p forn ul li h2-h7
行內元素: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響應頭之后,瀏覽器將會允許跨域請求
利用h6新特性window.postMessage()
iframe元素創建包含另外一個文檔的內聯框架(行內框架)(setTimeout進行異步加載)
解釋:瀏覽器中的瀏覽器!用于設置文本或者圖形的浮動圖文框或容器
它和跨域
1、document.domain 實現主域名相同,子域名不同的網頁通信
都設置為超域:document.domain = 'demo.com'
2、window.postMessageht(data, url),h6的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: 是h6的本地存儲庫,把一些數據存儲到瀏覽器中,沒網絡,瀏覽器可以從這里讀取數據,離線運用。5m
2.Cookie: 通過瀏覽器記錄信息確認用戶身份,最大4kb,這也就限制了傳輸的數據,請求的性能會受到影響
3.Session: 服務器端使用的一種記錄客戶狀態的機制(session_id存在set_cookie發送到客服端,保存為cookie)
4.localStroage: h6的本地存儲,數據永久保存在客服端
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、安全性問題。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。