如下問題基本針對於大廠一面和中等公司的一面二面,更多關於項目裏的問題還需根據自身參考。javascript
語義標籤,加強型表單,視頻和音頻,Canvas繪圖,SVG繪圖,地理定位,拖放API,Web Worker。
css
一塊獨立渲染區域。如下會造成BFC:html
做用:防止margin重疊,自適應兩欄佈局,清除內部浮動。前端
水平居中:text-align:center,,flex,position:absolute+transformvue
垂直居中:line-height,flex,position:absolute+transform,table-cellhtml5
水平垂直居中:flex,position:absolute+transform.java
static
是默認值relative
相對定位 相對於自身原有位置進行偏移,仍處於標準文檔流中absolute
絕對定位 相對於最近的已定位的祖先元素, 有已定位(指position
不是static
的元素)祖先元素, 以最近的祖先元素爲參考標準。若是無已定位祖先元素, 以body
元素爲偏移參照基準, 徹底脫離了標準文檔流。fixed
固定定位的元素會相對於視窗來定位,這意味着即使頁面滾動,它仍是會停留在相同的位置。一個固定定位元素不會保留它本來在頁面應有的空隙。display:none指的是元素徹底不陳列出來,不佔據空間,涉及到了DOM結構,故產生reflow與repaintnode
visibility:hidden指的是元素不可見但存在,保留空間,不影響結構,故只產生repaint(脫離文檔流)webpack
!important>inline>ID>class>taggit
這個問題呢,基本上是必問的。因此這一題,咱們從js的變量提及,從內存空間提及:
其中,JavaScript中變量類型有兩種:
Undefined, Null, Boolean, Number, String, Symbol
)一共6種Object
)基礎類型的值保存在棧中,這些類型的值有固定大小,"按值來訪問";
引用類型的值保存在堆中,棧中存儲的是引用類型的引用地址(地址指針),"按引用訪問",引用類型的值沒有固定大小,可擴展(一個對象咱們能夠添加多個屬性)。
所以進行拷貝的時候便分爲兩種拷貝:
關於js執行上下文:
執行上下文(Execution Context): 函數執行前進行的準備工做(也稱執行上下文環境)
js中執行上下環境(上下文):
由於js是單線程,所以,js代碼執行就相似於出棧,入棧過程。js中,全局永遠在棧底,代碼示例:
function foo () {
function bar () {
return 'I am bar';
}
return bar();
}
foo();複製代碼
從這裏能夠看出執行上下文的生命週期:
關於上下文不一樣階段的做用可參考這篇文章
什麼是原型:
每一個函數默認都有一個 prototype
屬性,它就是咱們所說的 "原型",或稱 "原型對象"。每一個實例化建立的對象都有一個 __proto__
屬性(隱式原型),它指向建立它的構造函數的 prototype
屬性。
什麼是原型鏈:(基本是基於構造函數)
訪問一個對象的屬性時,會先在其基礎屬性上查找,找到則返回值;若是沒有,會沿着其原型鏈上進行查找,整條原型鏈查找不到則返回 undefined
。這就是原型鏈查找。
function a(){};
a.prototype.name = "追夢子";
var b = new a();
console.log(b.name); //追夢子複製代碼
所以從原型咱們能夠談到繼承:
1.原型繼承
// 建立父類一個類
function Father(name){
//屬性
this.name = name || 'father'
// 實例方法
this.run = function(){
console.log(this.name + '正在跑步!');
}
}
//原型上的方法
Father.prototype.sayName = function() {
console.log(this.name+'正在跑步');
}
//原型鏈繼承
function Son(){
this.subName = '兒子'
}
// 建立Son的實例,並將原型指向Father
Son.prototype = new Father()
Son.prototype.saySubName = function() {
console.log(this.subName+'正在跑步');
}
var son = new Son()
console.log(son.sayName()) // father正在跑步
console.log(son) //能夠看看son的原型指向複製代碼
// 建立父類一個類
function Father(name){
//屬性
this.color = ['r','e']
}
//原型鏈繼承
function Son(){}
Son.prototype = new Father()
var sonOne = new Son()
sonOne.color.push('d')
console.log(sonOne.color)//["r", "e", "d"]
var sonTwo = new Son()
console.log(sonTwo.color)//["r", "e", "d"]
特色:基於原型鏈,既是父類的實例,也是子類的實例
缺點:對於上 引用型值的繼承容易形成全部實例共享複製代碼
2.構造函數繼承
// 建立父類一個類
function Father(name){
//屬性
this.color = name || ['r','e']
}
//原型上的方法
Father.prototype.sayColors = function() {
console.log(this.color);
}//構造函數繼承
function Son(){
Father.call(this) //只有函數纔會有call,apply,bind
}
// 實例1
var sonOne = new Son()
// 實例二
var sonTwo = new Son()
sonOne.color.push('d')
console.log(sonOne.color)//["r", "e", "d"]
console.log(sonTwo.color)// ["r", "e"]
console.log(sonTwo)
console.log(sonTwo instanceof Son) // true
console.log(sonTwo instanceof Father) //false
console.log('是否繼承了原型上方法', sonTwo.sayColors()) // error
特色: 能夠實現多繼承
缺點:只能繼承父類實例的屬性和方法,不能繼承原型上的屬性和方法,而且複用性太弱。複製代碼
3.組合式繼承:(原型繼承+構造繼承)
function Father(colors){
//屬性
this.color = colors || ['r','e']
}
//原型上的方法
Father.prototype.sayColors = function() {
console.log(this.color);
}
//構造函數繼承
function Son(name, color){
Father.call(this, color) //第二次調用Father()
this.name = name
this.sayName = function(){
console.log(this.name)
}
}
Son.prototype = new Father() //第一次調用Father()
var sonOne = new Son('兒子1', ['r','e', 'd'])
sonOne.sayColors() //["r", "e", "d"]
sonOne.sayName() //兒子1
var sonTwo = new Son('兒子2', ['g','r', 'e'])
sonTwo.sayColors() //["g", "r", "e"]
sonTwo.sayName() //兒子2
console.log(sonTwo) //如下圖片是sonTwo
特色:既繼承了實例的屬性和方法,也繼承了原型上的屬性和方法
缺點:調用了兩次父類構造函數,生成了兩份實例
複製代碼
4.寄生式組合繼承(不進行兩次調用,直接將父類原型複製給子類原型)
function Father(colors){
//屬性
this.color = colors || ['r','e']
}
//原型上的方法
Father.prototype.sayColors = function() {
console.log(this.color);
}
//構造函數繼承
function Son(name, colors){
Father.call(this, colors)
this.name = name
this.sayName = function(){
console.log(this.name)
}
}
function jisheng(subPro,superPro){
let pro = Object(superPro)
pro.constructor = subPro
subPro.prototype = pro }
jisheng(Son,Father)
var sonOne = new Son('兒子1', ['r','e', 'd'])
sonOne.sayColors() // ['r','e', 'd']
sonOne.sayName() // 兒子1
var sonTwo = new Son('兒子2', ['g','r', 'e'])
sonTwo.sayColors() // ['g','r', 'e']
sonTwo.sayName() // 兒子2
console.log(sonTwo) //如下是sonTwo的截圖複製代碼
什麼是做用域:(針對變量)
至關於針對這些變量的訪問權限的合集。(至關於一個省(全局做用域)下的各類市,縣。。。都有不一樣的地盤)
var globaValue = '我是省做用域';
function chengdu() {
var fooValue = '我是chengdu做用域'; function wuhou() {
var barValue = '我是wuhou做用域'; }
}
function mianyang() {
var otherValue = '我是mianyang做用域';
}複製代碼
什麼是做用域鏈:和原型鏈同樣,是一個查找過程
var a = 1;
var b = 2;
function b(){
var a = 2;
function c(){
var a = 3;
console.log(a);
console.log(b);
} c();
}
b();//3 2
當在c的做用域中找到a,就中止查找,打印a,繼續向上找b,b函數的做用域中沒有b,
則繼續沿着做用域鏈往上找,在全局中找到b。複製代碼
所以從做用域咱們能夠談到閉包:閉包就是指有權訪問另外一個函數做用域中的變量的函數。
// 如下就是閉包的應用
function test(){
var arr = [];
for(var i = 0;i < 10;i++){ //i是在test做用域裏
arr[i] = function(){ //函數二做用域
return i;
};
}
for(var a = 0;a < 10;a++){
console.log(arr[a]());
}
}
test(); //打印10個10,由於i在test執行的時候最後 for循環遍歷i變爲10,所以在函數二的做用域中沒有i,
就向上找。
//變量被保存在了內存中function test(){
var a = 1
return function(){
a++
console.log(a)
}
}
var func = test()
func() // 2
func() // 3
//閉包中的this指向
var name = "The Window";
var obj = {
name: "My Object",
getName: function(){
return function(){
return this.name;
};
}
};
console.log(obj.getName()()); // 其實是在全局做用域中調用了匿名函數,this指向了window。
//這裏要理解函數名與函數功能(或者稱函數值)是分割開的,不要認爲函數在哪裏,
//其內部的this就指向哪裏。匿名函數的執行環境具備全局性,所以其 this 對象一般指向 window。複製代碼
1. 建立一個新的對象,this變量引用該對象,同時還繼承了該函數的原型
2. 屬性和方法都被添加到this 引用的對象中去
3. 新建立的對象由this所引用,而且最後隱式的返回this
promise解決異步的三種狀態
(1) promise 對象初始化狀態爲 pending
(2) 當調用resolve(成功),會由pending => fulfilled
(3) 當調用reject(失敗),會由pending => rejected
注意promsie狀態 只能由 pending => fulfilled/rejected, 一旦修改就不能再變
在說區別以前,咱們先看一個例子
var p1 = new Promise(function(resolve, reject){
resolve(1);
})
setTimeout(function(){
console.log("will be executed at the top of the next Event Loop");
},0)
p1.then(function(value){
console.log("p1 fulfilled");
})
setTimeout(function(){
console.log("will be executed at the bottom of the next Event Loop");
},0)
p1 fulfilled
will be executed at the top of the next Event Loop
will be executed at the bottom of the next Event Loop複製代碼
。
JavaScript經過任務隊列管理全部異步任務,而任務隊列還能夠細分爲MacroTask Queue(宏任務)和MicoTask Queue(微任務)兩類。
MacroTask Queue(宏任務隊列)主要包括setTimeout,setInterval, setImmediate, requestAnimationFrame, NodeJS中的`I/O等。
MicroTask Queue(微任務隊列)主要包括兩類:
獨立回調microTask:如Promise,其成功/失敗回調函數相互獨立;
複合回調microTask:如 Object.observe, MutationObserver 和NodeJs中的 process.nextTick ,不一樣狀態回調在同一函數體;
總的來講就是若是代碼按順序執行,就是一個進入是最大的宏任務,先執行第一個宏任務而後執行宏任務裏的微任務,在執行下一個宏任務。
都是Tcp鏈接,最大的區別就是:
GET產生一個TCP數據包;POST產生兩個TCP數據包。
對於一個數據請求來講,能夠分爲發起網絡請求、後端處理、瀏覽器響應三個步驟。而瀏覽器則能幫助咱們在第一步和第三步優化性能,減小數據請求。
其中,緩存位置分爲四種:
Service Worker(運行在瀏覽器背後的獨立線程,必須使用https保障安全)
Memory Cache(內存中的緩存,讀取速度快,緩存持續性很短)
Disk Cache(存儲在硬盤中的緩存,讀取速度慢)
Push Cache(推送緩存,以上三種緩存都沒有命中時,它纔會被使用,會話中存在)
關於瀏覽器緩存能夠參照「深刻理解瀏覽器緩存機制」,如下是瀏覽器緩存過程分析(圖來自網絡):
是否須要向服務器從新發起HTTP請求將緩存過程分爲兩個部分:
- 強制緩存(不會向服務器發送請求,從緩存中讀取)
- 協商緩存(強制緩存失效,瀏覽器從新攜帶緩存標識發起請求,從而讓服務器決定是否啓用緩存的過程)
前端清理緩存的幾種方法:
//不緩存meta標籤
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="0">
//form表單
<body onLoad="javascript:document.yourFormName.reset()">
//ajax請求時
cache:false ||
beforeSend :function(xmlHttp){
xmlHttp.setRequestHeader("If-Modified-Since","0");
xmlHttp.setRequestHeader("Cache-Control","no-cache");
},
//url參數上加隨機數或者隨機時間
複製代碼
爲何須要cookie和session?
http是無狀態的,服務端不能跟蹤客戶端的狀態。
cookie機制:
若是不在瀏覽器中設置過時時間,cookie被保存在內存中,生命週期隨瀏覽器的關閉而結束,這種cookie簡稱會話cookie。若是在瀏覽器中設置了cookie的過時時間,cookie被保存在硬盤中,關閉瀏覽器後,cookie數據仍然存在,直到過時時間結束才消失。
Cookie是服務器發給客戶端的特殊信息,cookie是以文本的方式保存在客戶端,每次請求時都帶上它
session機制:
當服務器收到請求須要建立session對象時,首先會檢查客戶端請求中是否包含sessionid。若是有sessionid,服務器將根據該id返回對應session對象。若是客戶端請求中沒有sessionid,服務器會建立新的session對象,並把sessionid在本次響應中返回給客戶端。一般使用cookie方式存儲sessionid到客戶端,在交互中瀏覽器按照規則將sessionid發送給服務器。若是用戶禁用cookie,則要使用URL重寫,能夠經過response.encodeURL(url) 進行實現;API對encodeURL的結束爲,當瀏覽器支持Cookie時,url不作任何處理;當瀏覽器不支持Cookie的時候,將會重寫URL將SessionID拼接到訪問地址後。
cookie:大小限制4KB,會浪費一部分發送cookie時使用的帶寬,要正確的操縱cookie是很困難的。
webStorage包括如下兩種:數據存儲大小是5MB,字符串類型
localstorage:永久保存,除非手動清除clear()。
sessionstorage:臨時保存,關閉了瀏覽器窗口後就會被銷燬
原理: 惡意攻擊者往Web頁面裏插入惡意html代碼,當用戶瀏覽該頁之時,嵌入其中Web裏面的 (html代碼/javascript代碼) 會被執行,從而達到惡意攻擊用戶的特殊目的。
解決方法:過濾危險節點,cookie設置成httponly
原理:CSRF攻擊者在用戶已經登陸目標網站以後,誘使用戶訪問一個攻擊頁面,利用目標網站對用戶的信任,以用戶身份在攻擊頁面對目標網站發起僞造用戶操做的請求,達到攻擊目的。
解決方法:儘可能使用POST,限制GET;瀏覽器Cookie策略;加驗證碼;Referer Check;Anti CSRF Token服務端加token,在提交請求時附上,看是否與服務端一致。
HTTP
請求數DNS
查詢CDN
DOM
元素數量DOM
操做JavaScript
和 CSS
JavaScript
、 CSS
、字體、圖片等CSS Sprite
iconfont
iframe
使用src
爲空Object.defineProperty複製代碼
hash
---- 利用URL中的hash(「#」):HashHistory.push(),HashHistory.replace()
利用History
interface在 HTML5中新增的方法:pushState(), replaceState()
pushState設置的新URL能夠是與當前URL同源的任意URL;而hash只可修改#後面的部分,故只可設置與當前同文檔的URL
pushState設置的新URL能夠與當前URL如出一轍,這樣也會把記錄添加到棧中;而hash設置的新值必須與原來不同纔會觸發記錄添加到棧中
pushState經過stateObject能夠添加任意類型的數據到記錄中;而hash只可添加短字符串
pushState可額外設置title屬性供後續使用
v-if: 移除在dom中的顯示,將dom元素移除
v-show: dom元素還在,至關於display:none
display:none --元素被隱藏, 和 visibility: hidden
重排和重繪:重排包括重繪,重繪不必定包括重排
引發重排:
(1)頁面渲染初始化時;(這個沒法避免)
(2)瀏覽器窗口改變尺寸;
(3)元素尺寸改變時;
(4)元素位置改變時;
(5)元素內容改變時;
(6)添加或刪除可見的DOM 元素時。
git pull至關於git fecth + git merge。git fecth只能改變遠程倉庫裏的代碼,本地head不能改變。
爲何須要source-map,爲了解決代碼通過編譯打包出錯以後定位問題。
webpack官網一共有11種,無非就是包括:打包後(none),生成後的代碼,轉換後的代碼(僅限行:每行一個映射),原始源代碼(僅限行),原始源代碼,無源代碼內容。對於開發環境,一般但願更快速的 source map,須要添加到 bundle 中以增長體積爲代價,可是對於生產環境,則但願更精準的 source map,須要從 bundle 中分離並獨立存在。
如下是開發環境經常使用推薦的:
配置:devtool: 'cheap-eval-source-map'
生產環境是最好不要看到源碼,推薦devtool:none