前端面试题总结-初级
HTTP協議
說一下 http 和 http ?
http 是超文本傳輸協議,信息是明文傳輸 Https 是加密的、協議需要 ca 證書,費用較高。https缺點: https 握手階段比較費時,會使頁面加載時間延長 50%,增加 10%~20%的耗電。 https 緩存不如 http 高效,會增加數據開銷。 SSL 證書也需要錢,功能越強大的證書費用越高。 SSL 證書需要綁定 IP,不能再同一個 ip 上綁定多個域名,ipv4 資源支持不了這種消耗。tcp 三次握手,一句話概括
TCP 和 UDP 的區別
TCP 是面向連接的,udp 是無連接的即發送數據前不需要先建立鏈接。 TCP 提供可靠的服務。面向連接,不會丟失數據因此適合大數據量的交換。TCP 只能是 1 對 1 的,UDP 支持 1 對 1,1 對多。TCP 是面向連接的可靠性傳輸,而 UDP 是不可靠的說一下 http2.0
說一下 http2.0提升了速度 內容安全,應為 http2.0 是基于 https 的 允許多路復用: 傳輸信息進行二進制編碼和分幀 服務器端推送多路復用允許同時通過單一的 HTTP/2 連接發送多重請求-響應信息。改 善了:在 http1.1 中,瀏覽器客戶端在同一時間,針對同一域名下的請求有一定數量限 制(連接數量),超過限制會被阻塞。 :HTTP2.0 會將所有的傳輸信息分割為更小的信息或者幀,并對他們進行二進制編碼 首部壓縮狀態碼:
200 表示請求成功301 永久重定向 302 臨時重定向 304 get請求被允許但是,但是內容和請求條件沒有改變400 請求無效,前端提交數據的字段名稱和字段類型與后臺不一致,將 obj 對象通過 JSON.stringify 401 當前請求需要用戶驗證 403 雖然服務器已經得到請求,但是拒絕執行請求被拒絕 404 找不到資源或者接口不存在5XX 表示服務端錯誤 500 服務器端的未知錯誤 502 網關錯誤 503 服務暫時無法使用肯定會碰到: 101/200/301/302/304/400/404/502補充 400 和 401、403 、304狀態碼
(1)400 狀態碼:請求無效 產生原因:前端提交數據的字段名稱和字段類型與后臺的實體沒有保持一致 前端提交到后臺的數據應該是 json 字符串類型,但是前端沒有將對象 JSON.stringify 轉化成字符串。解決方法: 對照字段的名稱,保持一致性,將 obj 對象通過 JSON.stringify 實現序列化(2)401 狀態碼:當前請求需要用戶驗證 (3)403 狀態碼:服務器已經得到請求,但是拒絕執行304:如果客戶端發送了一個帶條件的 GET 請求且該請求已被允許,內容和請求條件并沒有改變,就會返回304對 HTML 語義化標簽的理解
雙閉合標簽,便于閱讀,比如 nav表示導航條,類似的還有 article、header、footer 等等標簽GET 和 POST 的區別 參考回答
get 參數通過 url 傳遞, post 放在 request body 中。 get 請求參數會被完整保留在瀏覽歷史記錄里,而 post 中的參數不會被保留GET 產生一個 TCP 數據包;POST 產生兩個 TCPHTTP 支持的方法
get、post,這兩個用的是最多的,還有很多比如 patch、delete、put、options 等等描述一下 XSS 和 CRSF 攻擊?防御方法?
XSS(跨站腳本攻擊): 向網站注入JS代碼,然后執行,篡改網站的內容1. 輸入過濾 限制輸入框文本長度,過濾特殊字符( <> ... )2. 在HTTP頭部上配置,set-cookieHttponly :禁止Js訪問Cookie。Secure : 僅當在https請求時發送CookieCSRF 跨站請求偽造 是利用網站本身的漏洞請求網站的api。驗證 HTTP Referer 字段;在請求地址中添加 token 并驗證;在 HTTP 頭中自定義屬性并驗SQL注入 用戶輸入的文本框中不可以有特殊符號( 引號、空格 )面試題基礎篇
1.1 HTML面試題
行內元素有哪些?塊級元素有哪些? 空(void)元素有哪些?
行內元素:span、img、input... 塊級元素:div、footer、header、section、p、h1...h6... 空元素:br、hr...元素之間的轉換問題: display: inline; 把某元素轉換成了行內元素 ===> 不獨占一行的,并且不能設置寬高 display: inline-block; 把某元素轉換成了行內塊元素 ===> 不獨占一行的,可以設置寬高 display: block; 把某元素轉換成了塊元素 ===> 獨占一行,并且可以設置寬高HTML5新增標簽:
增加了 header,footer,nav,aside,section 等語義化標簽 為 input 增加了 color,emial,data ,range 等類型, 提供了 sessionStorage,localStorage 多媒體 audio 和 vedio 另外還有地理定位,canvas畫布,canvas 繪圖,支持SVGcss3: border-radius,box-shadow; background-size,background-origin; CSS3 2D,3D 轉換、transform;animation 動畫頁面導入樣式時,使用link和@import有什么區別?
區別一:link先有,后有@import(兼容性link比@import兼容); 區別二:加載順序差別,瀏覽器先加載的標簽link,后加載@importtitle與h1的區別、b與strong的區別、i與em的區別?
title與h1的區別:定義:title:概括了網站信息,可以告訴搜索引擎或者用戶關于這個網站的內容主題是什么h1:文章主題內容,告訴蜘蛛我們的網站內容最主要是什么 區別:title他是顯示在網頁標題上、h1是顯示在網頁內容上title比h1添加的重要 (title > h1 ) ==》對于seo的了解 場景:網站的logo都是用h1標簽包裹的 b與strong的區別:定義:b:實體標簽,用來給文字加粗的。strong:邏輯標簽,用來加強字符語氣的。 區別:b標簽只有加粗的樣式,沒有實際含義。strong表示標簽內字符比較重要,用以強調的。題外話:為了符合css3的規范,b盡量少用該用strong就行了。 i與em的區別:定義:i:實體標簽,用來做文字傾斜的。em:是邏輯標簽,用來強調文字內容的 區別:i只是一個傾斜標簽,沒有實際含義。em表示標簽內字符重要,用以強調的。 場景:i更多的用在字體圖標,em術語上(醫藥,生物)。img標簽的title和alt有什么區別?
區別一:title : 鼠標移入到圖片顯示的值alt : 圖片無法加載時顯示的值 區別二:在seo的層面上,蜘蛛抓取不到圖片的內容,所以前端在寫img標簽的時候為了增加seo效果要加入alt屬性來描述這張圖是什么內容或者關鍵詞。png、jpg、gif 這些圖片格式解釋一下,分別什么時候用?
png:無損壓縮,尺寸體積要比jpg/jpeg的大,適合做小圖標。 jpg:采用壓縮算法,有一點失真,比png體積要小,適合做中大圖片。 gif:一般是做動圖的。 webp:同時支持有損或者無損壓縮,相同質量的圖片,webp具有更小的體積。兼容性不是特別好。1.2 CSS面試題
介紹一下CSS的盒子模型
CSS的盒子模型有哪些:標準盒子模型、IE盒子模型 CSS的盒子模型區別:標準盒子模型:margin、border、padding、contentIE盒子模型 :margin、content( border + padding + content ) 通過CSS如何轉換盒子模型:box-sizing: content-box; /*標準盒子模型*/box-sizing: border-box; /*IE盒子模型*/line-height和heigh區別【大廠】
line-height 是每一行文字的高,如果文字換行則整個盒子高度會增大(行數*行高)。 height 是一個死值,就是這個盒子的高度。CSS選擇符有哪些?哪些屬性可以繼承?
CSS選擇符:通配(*)id選擇器(#)類選擇器(.)標簽選擇器(div、p、h1...)相鄰選擇器(+)后代選擇器(ul li)子元素選擇器( > )屬性選擇器(a[href])CSS屬性哪些可以繼承:文字系列:font-size、color、line-height、text-align... ***不可繼承屬性:border、padding、margin...CSS優先級算法如何計算?
優先級比較:!important > 內聯樣式 > id > class > 標簽 > 通配 CSS權重計算: 第一:內聯樣式(style) 權重值:1000 第二:id選擇器 權重值:100 第三:類選擇器 權重值:10 第四:標簽&偽元素選擇器 權重值:1 第五:通配、>、+ 權重值:0用CSS畫一個三角形
用邊框畫(border),例如: {width: 0;height: 0;border-left:100px solid transparent;border-right:100px solid transparent;border-top:100px solid transparent;border-bottom:100px solid #ccc; }畫一條 0.5px 的線
1. 采用 meta viewport 的方式 (縮放0.5 移動端才有效果)<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />3.transform: scale()垂直居中的方法
定位為上下左右為 0,margin:0 可以實現脫離文檔流的居中. margin 負值法 -height 的一半 -width 的一半 transform:translateX(-50%)和 transform:translateY(-50%)垂直居中設置line-height 等于height display:flex + align-items: center display:table+display:table-cell + vertical-align: middle;一個盒子不給寬度和高度如何水平垂直居中?
方式一:彈性盒
<div class='container'><div class='main'>main</div> </div>.container{display: flex;justify-content: center;align-items: center;width: 300px;height: 300px;border:5px solid #ccc; } .main{background: red; }方式二: transform
<div class='container'><div class='main'>main</div> </div>.container{position: relative;width: 300px;height: 300px;border:5px solid #ccc; } .main{position: absolute;left:50%;top:50%;background: red;transform: translate(-50%,-50%); }方式二:grid 網格布局 (用的少)
<div class='container'><div class='main'>main</div> </div>.container{display: grid;justify-content: center;align-items: center;width: 300px;height: 300px;border:5px solid #ccc; } .main{background: red; }display有哪些值?說明他們的作用。
none 隱藏元素 block 把某某元素轉換成塊元素 inline 把某某元素轉換成內聯元素 inline-block 把某某元素轉換成行內塊元素BFC(塊級格式化上下文,用于清楚浮動,防止 margin 重疊等)
BFC 是頁面上的一個獨立容器,子元素不會影響到外面元素2. BFC的原則:如果一個元素具有BFC,那么內部元素再怎么弄,都不會影響到外面的元素。 3. 如何觸發BFC:float的值非noneoverflow的值非visibledisplay的值為:inline-block、table-cell...position的值為:absoute、fixed清除浮動有哪些方式?
1. 觸發BFC 2. 多創建一個盒子,添加樣式:clear: both; 3. after方式ul:after{content: '';display: block;clear: both;}在網頁中的應該使用奇數還是偶數的字體?為什么呢?
偶數 : 讓文字在瀏覽器上表現更好看。另外說明:ui給前端一般設計圖都是偶數的,這樣不管是布局也好,轉換px也好,方便一點。position有哪些值?分別是根據什么定位的?
static [默認] 沒有定位 fixed 固定定位,相對于瀏覽器窗口進行定位。 relative 相對于自身定位,不脫離文檔流。 absolute 相對于第一個有relative的父元素,脫離文檔流。relative和absolute區別 1. relative不脫離文檔流 、absolute脫離文檔流 2. relative相對于自身 、 absolute相對于第一個有relative的父元素 3. relative如果有left、right、top、bottom ==》left、topabsolute如果有left、right、top、bottom ==》left、right、top、bottom寫一個左中右布局占滿屏幕,其中左、右倆塊固定寬200,中間自適應寬,要求先加載中間塊,請寫出結構及樣式。
雙飛翼: left、center、right三種都設置左浮動 設置center寬度為100% 設置負邊距,left設置負邊距為100%,right設置負邊距為自身寬度 設置content的margin值為左右兩個側欄留出空間,margin值大小為left和right寬度什么是CSS reset?
reset.css 是一個css文件,用來重置css樣式的。 normalize.css 為了增強跨瀏覽器渲染的一致性,一個CSS 重置樣式庫。css sprite 精靈圖 是什么,有什么優缺點
1. 是什么把多個小圖標合并成一張大圖片。 2. 優缺點優點:減少了http請求的次數,提升了性能。缺點:維護比較差(例如圖片位置進行修改或者內容寬高修改)display: none;與visibility: hidden;的區別
1. 占用位置的區別 display: none; 是不占用位置的 visibility: hidden; 雖然隱藏了,但是占用位置2. 重繪和回流的問題 display: none; 頁面產生重繪+回流 visibility: hidden; 產生重繪display: none 會影響計數器 visibility: hidden 不會影響計數器,且具有繼承性,比如父盒子設置了visibility: hidden,子元素會繼承該屬性,當子元素再次設置 visibility: visible,元素又會顯示。產生回流一定會造成重繪,但是重繪不一定會造成回流。產生回流的情況:改變元素的位置(left、top...)、顯示隱藏元素.... 產生重繪的情況:樣式改變、換皮膚重繪和回流
什么是重繪?
樣式改變不影響文檔流時, background、boder-color、visibility等。
什么是回流?
元素的尺寸、布局、隱藏等改變時候、造成瀏覽器重新渲染部分DOM或全部DOM的過程。
如何減少回流和重繪?
在css中:在dom的最末端改變class避免設置多層內聯樣式避免使用table布局使用 transfrom、opacity、filter等動畫效果不會造成重繪問題 在js中:避免一個樣式修改完接著下一個樣式 (應該一次性改好,或者定義class類)避免重復操作dom,(使用文檔創建子樹,然后拷貝到文檔中)復雜動畫使用絕對定位讓其脫離文檔流,否則會引起父元素和后續元素大量回流。opacity 和 rgba區別
共同性:實現透明效果1. opacity 取值范圍0到1之間,0表示完全透明,1表示不透明 2. rgba R表示紅色,G表示綠色,B表示藍色,取值可以在正整數或者百分數。A表示透明度取值0到1之間區別:繼承的區別 opacity會繼承父元素的opacity屬性,而RGBA設置的元素的后代元素不會繼承不透明屬性。1.3 JavaScript基礎面試題
延遲加載JS有哪些方式?
延遲加載:async、defer例如:<script defer type="text/javascript" src='script.js'></script>defer : 等html全部解析完成,才會執行js代碼,順次執行js腳本。 async : async是和html解析同步的(一起的),不是順次執行js腳本(誰先加載完誰先執行)。JS數據類型有哪些?
基本類型:string、number、boolean、undefined、null、symbol、bigint引用類型:object (arr、fun是引用類型的小類,也是object)NaN是一個數值類型,但是不是一個具體的數字。JS數據類型考題
考題一:
-
布爾值和num相加 布爾會轉換成 1/2
-
字符串和其他類型相加 另一個都會變為字符串類型
-
typeof(null) 是一個特殊的對象類型
考題二:
console.log( typeof(NaN) ); //number console.log( typeof(null) ); //objectnull 和 undefined的區別
1. 作者在設計js的都是先設計的null(為什么設計了null:最初設計js的時候借鑒了java的語言) 2. null會被隱式轉換成0,很不容易發現錯誤。 3. 先有null后有undefined,出來undefined是為了填補之前的坑。具體區別:JavaScript的最初版本是這樣區分的:null是一個表示"無"的對象(空對象指針),轉為數值時為0;undefined是一個表示"無"的原始值,轉為數值時為NaN。和=有什么不同?
== : 比較的是值string == number || boolean || number ....都會隱式轉換通過valueOf轉換(valueOf() 方法通常由 JavaScript 在后臺自動調用,并不顯式地出現在代碼中。)=== : 除了比較值,還比較類型JS微任務和宏任務
就是異步的事件隊列里面分為宏任務和微任務。
1. js是單線程的語言。 2. js代碼執行流程:同步執行完==》事件循環同步的任務都執行完了,才會執行事件循環的內容進入事件循環:請求、定時器、事件....3. 事件循環中包含:【微任務、宏任務】 宏任務:setTimeout、異步ajax請求、文件操作等 微任務:Promise.then、.catch 和 .finally 要執行宏任務的前提是清空了所有的微任務流程:先執行同步的==》再執行事件循環里的微任務和宏任務 ==》微任務==》宏任務=》微任務...JS作用域考題
1. 除了函數外,js是沒有塊級作用域。2. 作用域鏈:內部可以訪問外部的變量,但是外部不能訪問內部的變量。注意:如果內部有,優先查找到內部,如果內部沒有就查找外部的。3. 注意聲明變量是用var還是沒有寫(window.)(function(){var a = b = 10})()console.log(a) // 報錯console.log(b) // 10 因為b沒有被var定義,是全局變量(window.b)4. 注意:js有變量提升的機制【變量懸掛聲明】 5. 優先級:聲明變量 > 聲明普通函數 > 參數 > 變量提升面試的時候怎么看:
1. 本層作用域有沒有此變量【注意變量提升】 2. 注意:js除了函數外沒有塊級作用域 3. 普通聲明函數時不看寫函數的時候順序考題一:
function c(){var b = 1;function a(){console.log( b );var b = 2;console.log( b );}a();console.log( b ); } c();// undefind 2 1 注意變量提升考題二:
var name = 'a'; (function(){if( typeof name == 'undefined' ){var name = 'b';console.log('111'+name);}else{console.log('222'+name);} })() // 222a 錯誤 js除了函數外沒有塊級作用域,fun 里面有定義b // 正確應該是 111b考題三:
function fun( a ){var a = 10;function a(){}console.log( a ); } fun( 100 ); // 10// 優先級:聲明變量 > 聲明普通函數 > 參數 > 變量提升JS對象考題
JS對象注意點:
1. 對象是通過new操作符構建出來的,所以對象之間不相等(除了引用外); 2. 對象注意:引用類型(共同一個地址); 3. 對象的key都是字符串類型; 4. 對象如何找屬性|方法;查找規則:先在對象本身找 ===> 構造函數中找 ===> 對象原型中找 ===> 構造函數原型中找 ===> 對象上一層原型查找考題一:
[1,2,3] === [1,2,3] //false考題二:
var obj1 = {a:'hellow' } var obj2 = obj1; obj2.a = 'world'; console.log(obj1); //{a:world} (function(){console.log(a); //undefinedvar a = 1; })();考題三:
var a = {} var b = {key:'a' } var c = {key:'c' }a[b] = '123'; //key 不應該是一個對象,如果是對象會被轉換成字符串'object Object ' a[c] = '456'; // 替換[b]console.log( a[b] ); // 456 var a = {};var b = { key: "a" };var c = { key: "c" };//b要作為屬性名先轉為字符串,相當于:a[object Object]:="123"a[b] = "123";//同上,c要作為屬性名先轉為字符串,相當于:a[object Object]:="456"a[c] = "456";//上面的a[c] = "456"只是給a[object Object]重新賦值而已。//打印a[b]其實就是在打印a[object Object],由于他的最一次的賦值為456。//故:console.log(a[b]);//456因為key名稱只能是字符串,b/c單做鍵會調用toString得到的都是[object Object],a[b],a[c]都等價于a["[object Object]"],所以后面的賦值會覆蓋前一次操作,打印的時候a[b]也是同理,那不就是更新[object Object]這個鍵的值了。
JS作用域+this指向+原型的考題
考題一:
function Foo(){getName = function(){console.log(1)} //注意是全局的window.return this; }Foo.getName = function(){console.log(2)} Foo.prototype.getName = function(){console.log(3)} var getName = function(){console.log(4)} function getName(){console.log(5) }Foo.getName(); //2 getName(); //4Foo().getName(); //1 getName(); //1new Foo().getName();//3考題二:
var o = {a:10,b:{a:2,fn:function(){console.log( this.a ); // 2console.log( this ); //代表b對象}} } o.b.fn(); // 2 {a:2,fn{}}考題三:
window.name = 'ByteDance'; function A(){this.name = 123; } A.prototype.getA = function(){console.log( this );return this.name + 1; } let a = new A(); let funcA = a.getA; funcA(); //this代表window考題四:
var length = 10; function fn(){return this.length + 1; } var obj = {length:5,test1:function(){return fn();} } obj.test2 = fn; console.log( obj.test1() ); //1 console.log( fn()===obj.test2() ); //false console.log( obj.test1() == obj.test2() ); //falseJS判斷變量是不是數組,你能寫出哪些方法?
方式一:isArray
var arr = [1,2,3]; console.log( Array.isArray( arr ) );方式二:instanceof 【如果網頁中使用多個框架會有問題,可能出現不同的數組構造函數】
var arr = [1,2,3]; console.log( arr instanceof Array );方式三:原型prototype
var arr = [1,2,3]; console.log( Object.prototype.toString.call(arr).indexOf('Array') > -1 );方式四:isPrototypeOf()
var arr = [1,2,3]; console.log( Array.prototype.isPrototypeOf(arr) )方式五:constructor
var arr = [1,2,3]; console.log( arr.constructor.toString().indexOf('Array') > -1 )slice是干嘛的、splice是否會改變原數組
1. slice是來截取的參數可以寫slice(3)、slice(1,3)、slice(-3)返回的是一個新的數組 2. splice 功能有:插入、刪除、替換返回:刪除的元素該方法會改變原數組數組排序
arr.sort((n1,n2)=>n1-n2) //正序排序 arr.sort((n1,n2)=>n2-n1) // 降序排序Math.max(...arr) // 求最大值 Math.min(...arr) // 求最小值arr.splice(9, 1);刪除后數組中索引9的元素 并返回刪除的值arr.splice(arr.findIndex((e) => e.id === 1), 1) //數組包含對象arr.splice(arr.findIndex((e,index) => index === 2), 1) //返回的是刪除后的數組JS數組去重
方式一:new set
var arr1 = [1,2,3,2,4,1];// new set返回的是一個對象,把它轉換成數組,兩種方法console.log(Array.from(new Set(arr1)));function unique(arr){return [...new Set(arr)] } console.log(unique(arr1) );方式二:indexOf
var arr2 = [1,2,3,2,4,1]; function unique( arr ){var brr = [];for( var i=0;i<arr.length;i++){// 等于-1說明沒找到if( brr.indexOf(arr[i]) == -1 ){brr.push( arr[i] );}}return brr; } console.log( unique(arr2) );方式三:sort
var arr3 = [1,2,3,2,4,1]; function unique( arr ){arr = arr.sort();var brr = [];for(var i=0;i<arr.length;i++){if( arr[i] !== arr[i-1]){brr.push( arr[i] );}}return brr; } console.log( unique(arr3) );找出多維數組最大值
function fnArr(arr){var newArr = [];arr.forEach((item,index)=>{newArr.push( Math.max(...item) )})return newArr; } console.log(fnArr([[4,5,1,3],[13,27,18,26],[32,35,37,39],[1000,1001,857,1] ]));給字符串新增方法實現功能
給字符串對象定義一個addPrefix函數,當傳入一個字符串str時,它會返回新的帶有指定前綴的字符串,例如:
console.log( ‘world’.addPrefix(‘hello’) ) 控制臺會輸出helloworld
解答: String.prototype.addPrefix = function(str){return str + this; } console.log( 'world'.addPrefix('hello') )找出字符串出現最多次數的字符以及次數
找出字符串出現次數返回一個對象:
var str = 'abccbaam' function funique(){let obj = {};for(let i = 0; i<str.length; i++){obj[str[i]] ? obj[str[i]] += 1 : obj[str[i]] = 1}return obj; } console.log(funique(str));找出字符串出現最多次數的字符以及次數
var str = 'aaabbbbbccddddddddddx'; var obj = {}; for(var i=0;i<str.length;i++){var char = str.charAt(i); //str[i]if( obj[char] ){obj[char]++;}else{obj[char] = 1;} } console.log( obj );//統計出來最大值 var max = 0; for( var key in obj ){if( max < obj[key] ){max = obj[key];} }//拿最大值去對比 for( var key in obj ){if( obj[key] == max ){console.log('最多的字符是'+key);console.log('出現的次數是'+max);} }js解析url參數為一個對象
function querUrlparms(url) {let obj = {}if (url.indexOf('?') < 0) return objlet arr = url.split('?')[1].split('&')for (let i = 0; i < arr.length; i++) {const arr2 = arr[i].split('='); obj[arr2[0]] = arr2[1] // 組合成鍵值對的形式}return obj }console.log(querUrlparms('https://www.baidu.com/s?wd=js&rsv_spt=1&rsv_iqid=0xfa41b9e2000013a3&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&rsv_sug3=4&rsv_sug2=0&rsv_btype=i&inputT=397&rsv_sug4=855'));使用 正則+ …arg
function queryURLparamsRegEs6(url) {let obj = {}let reg = /([^?=&]+)=([^?=&]+)/gurl.replace(reg, (...arg) => {obj[arg[1]] = arg[2]})return obj }new操作符具體做了什么
1. 創建了一個空的對象 2. 將空對象的原型,指向于構造函數的原型(原型賦值) 3. 將空對象作為構造函數的上下文(改變this指向,指向于新的對象) 4. 對構造函數有返回值的處理判斷 (如果構造函數返回基本類型,則構造函數的return無效,返回對象則new操作符無效) function Fun( age,name ){this.age = age;this.name = name; } function create( fn , ...args ){//1. 創建了一個空的對象var obj = {}; //var obj = Object.create({})//2. 將空對象的原型,指向于構造函數的原型Object.setPrototypeOf(obj,fn.prototype);//3. 將空對象作為構造函數的上下文(改變this指向)var result = fn.apply(obj,args);//4. 對構造函數有返回值的處理判斷return result instanceof Object ? result : obj; } console.log( create(Fun,18,'張三') )閉包
普通一個函數,執行完后,函數以及內部的變量就被銷毀了, 如果在這個函數里面又新建了一個函數,然后在普通函數內調用了外部函數的變量,此時就形成了一個閉包,當函數執行完畢,外部函數不被銷毀,造成了變量駐留在內存中,實現了無意的環境共享。
1. 閉包是什么閉包的實質是因為函數嵌套而形成的作用域鏈閉包是一個函數加上到創建函數的作用域的連接,閉包“關閉”了函數的自由變量。2. 閉包可以解決什么問題【閉包的優點】 2.1 內部函數可以訪問到外部函數的局部變量2.2 閉包可以解決的問題var lis = document.getElementsByTagName('li');for(var i=0;i<lis.length;i++){(function(i){lis[i].onclick = function(){alert(i);}})(i)} 3. 閉包的缺點3.1 變量會駐留在內存中,造成內存損耗問題。解決:把閉包的函數設置為null3.2 內存泄漏【ie】 ==> 可說可不說,如果說一定要提到ie原型鏈
1. 什么是原型? 原型可以解決什么問題實現 對象屬性和方法共享2. 誰有原型 函數擁有:prototype 對象擁有:__proto__3. 原型鏈是什么?就是把原型串聯起來(對象的屬性和方法可以在對象本身也可以放在原型中)先在對象本身查找 --> 構造函數中查找 --> 對象的原型 --> 構造函數的原型中 --> 當前原型的原型中查找4.2 原型鏈的最頂端是null(查找到null會返回undefined)原型鏈的數據結構: 鏈表結構,通過__proto__指針把每個原型串聯起來。 先在對象本身查找 --> 構造函數中查找 --> 對象的原型 --> 構造函數的原型中 --> 當前原型的原型中查找function Fun(){//this.run = '1' -> 2.構造函數中查找 } //Fun.prototype.run = '2' -> 4.構造函數的原型中var obj = new Fun();//obj.run = '3'; -> 1.先在對象本身查找 //obj.__proto__.run = '4' -> 3. 對象的原型Object.prototype.run = '5'; // -> 5. 當前原型的原型中查找console.log( obj.run ) // console.log( Fun.prototype , obj.__proto__ ) // console.log( obj.__proto__.__proto__.__proto__ ); // nullJS繼承有哪些方式
方式一:ES6 的class繼承
class Parent{constructor(){this.age = 18;} }class Child extends Parent{constructor(){super(); //雖然語法沒問題,但是不加super(),瀏覽器會報錯this.name = '張三';} } let o1 = new Child(); console.log( o1,o1.name,o1.age );方式二:原型鏈繼承
這里會出現一個問題,類似于淺拷貝,是地址的引用,所有屬性和方法都來自于原型,所有new 出來的對象都共用一個方法或屬性,改變一個屬性值會互相影響.
function Parent(){this.age = 20; } function Child(){this.name = '張三' } Child.prototype = new Parent(); let o2 = new Child(); console.log( o2,o2.name,o2.age );方式三:借用構造函數繼承
所有屬性和方法都是獨立的。
function Parent(){this.age = 22; } function Child(){this.name = '張三'Parent.call(this); } let o3 = new Child(); console.log( o3,o3.name,o3.age );方式四:組合式繼承
提取了原型繼承和借用構造函數繼承的優點。不共享的用call,共享的則指向原型。
function Parent(){this.age = 100; } function Child(){Parent.call(this);this.name = '張三' } Child.prototype = new Parent(); // 如果利用對象的形式修改了原型對象,別忘了利用constructor 指回原來的構造函數 Child.prototype.constructor = Son; let o4 = new Child(); console.log( o4,o4.name,o4.age );說一下call、apply、bind區別
共同點:功能一致
可以改變this指向語法: 函數.call()、函數.apply()、函數.bind()區別:
1. call、apply可以立即執行。bind不會立即執行,因為bind返回的是一個函數需要加入()執行。 2. 參數不同:apply第二個參數是數組。call和bind有多個參數需要挨個寫。場景:
1. 用apply的情況 var arr1 = [1,2,4,5,7,3,321]; console.log( Math.max.apply(null,arr1) )2. 用bind的情況 var btn = document.getElementById('btn'); var h1s = document.getElementById('h1s'); btn.onclick = function(){console.log( this.id ); }.bind(h1s)sort背后原理是什么?
V8 引擎 sort 函數只給出了兩種排序 InsertionSort 和 QuickSort,數量小于10的數組使用 InsertionSort,比10大的數組則使用 QuickSort。之前的版本是:插入排序和快排,現在是冒泡原理實現鏈接:https://github.com/v8/v8/blob/ad82a40509c5b5b4680d4299c8f08d6c6d31af3c/src/js/array.js***710行代碼開始***深拷貝和淺拷貝
共同點:復制1. 淺拷貝:只復制引用,而未復制真正的值。 var arr1 = ['a','b','c','d']; var arr2 = arr1;var obj1 = {a:1,b:2} var obj2 = Object.assign(obj1);2. 深拷貝:是復制真正的值 (不同引用) var obj3 = {a:1,b:2 } var obj4 = JSON.parse(JSON.stringify( obj3 ));//遞歸的形式 function copyObj( obj ){Array.isArray(obj) ? var newObj = [] : var newObj = {}for( var key in obj ){if( typeof obj[key] == 'object' ){newObj[key] = copyObj(obj[key]);}else{newObj[key] = obj[key];}}return newObj; } console.log( copyObj(obj5) );localStorage、sessionStorage、cookie的區別
公共點:在客戶端存放數據 區別: 1. 數據存放有效期sessionStorage : 會話存儲,當前窗口關閉后就會刪除。localStorage : 持久化存儲,始終有效,窗口或者瀏覽器關閉也一直保存。cookie : 只在設置的cookie過期時間之前有效,即使窗口或者瀏覽器關閉也有效。 2. localStorage、sessionStorage不可以設置過期時間cookie 有過期時間,可以設置過期,使用時需要環境(把時間調整到之前的時間,就過期了) 3. 存儲大小的限制cookie存儲量不能超過4klocalStorage、sessionStorage不能超過5M****根據不同的瀏覽器存儲的大小是不同的。1.4 H5/C3面試題
什么是語義化標簽
1. 易讀性和維護性更好。 2. seo成分會更好,蜘蛛抓取更好。 3. IE8不兼容HTML5標簽的。解決:可以通過html5shiv.js去處理。::before 和 :after中雙冒號和單冒號 有什么區別?解釋一下這2個偽元素的作用。
1. 區別:是偽類、::偽元素 ===》是為了做區分2.是什么?作用元素before之前 、 元素after之后作用:清除浮動、樣式布局上也有作用怎么讓Chrome支持小于12px 的文字?
Chrome默認字體大小是:16px **每個瀏覽器默認字體大小可能都不一樣<style type="text/css"> div{font-size:10px; } div span{display: inline-block;-webkit-transform:scale(1.6); } </style>rem和em區別
相對于font-sizeem針對于父元素的font-size rem針對于根(html)元素的font-sizewebkit表單輸入框placeholder的顏色值能改變嗎?
<style type="text/css">input::-webkit-input-placeholder{color:red;} </style>自適應
淘寶無限適配【移動端】:淘寶無限適配 + 布局單位使用rem響應式
1. 是什么?一個URL可以響應多端 2. 語法結構@media only screen and (max-width: 1000px){ul li:last-child{display: none;}}only : 可以排除不支持媒體查詢的瀏覽器screen : 設備類型max-width | max-heightmin-width | min-height 3. 響應式圖片【性能優化】<picture><source srcset="1.jpg" media='(min-width:1000px)'><source srcset="2.jpg" media='(min-width:700px)'><img srcset="3.jpg"></picture>布局方案
一、什么情況下采用響應式布局數據不是特別多,用戶量不是特別大,純展示類的項目適合響應式布局例如:公司的官網、專題頁面特別追求性能的項目,不太適合響應式,因為如果添加了很多的響應式就會造成加載速度變慢。二、pc + 移動端應該做什么樣的布局方案注意:訪問量還可以或者比較大,類似于淘寶網。pc是一套,會加入一點點響應式。移動端是一套,會使用自適應的布局方式。三、pc的設計圖ui:1980筆記本電腦:1280ui圖的寬度和電腦的寬度不對應該怎么辦?1. 把ui圖進行等比縮放,縮放成和電腦一樣的尺寸2. 換1980的電腦四、移動端的設計圖寬度:750因為750設計圖/2就是375,正好是iphone6的尺寸,我們要把iphone6的尺寸做為基準點。1.5 移動端頁面樣式兼容
移動端樣式重置
Normalize.css 跨瀏覽器端樣式重置,所有瀏覽器顯示一致。
解決移動端300ms延遲問題
為什么存在300ms延遲?
因為移動端雙擊屏幕默認會有放大效果,所有存在300ms延遲 (等待點擊第二次)。
在移動端使用click事件有300ms延遲的問題 解決方式:
禁止雙擊縮放
// html頭部 meta 標簽加入: mate:user-scalable=no使用插件 fastclick.js
// 引入js文件寫入代碼:if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); }移動端touch事件有穿透(點透)的問題,該怎么解決?
移動端的事件 (touch)
-
touchstart :開始觸摸事件
-
touchmove : 手指滑動事件
-
touchend : 觸摸結束事件
解決方式:
1、阻止默認行為 e.preventDefault();
2、fastclick.js
// 引入js文件 2.2 寫入代碼 if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false);ios 樣式問題
如何關閉IOS鍵盤首字母自動大寫
<input type="text" autocapitalize='off'>ios日期轉換NAN問題
具體就是,new Date('2020-11-12 00:00:00') 在ios中會為NAN 解決方案:用new Date('2020/11/12 00:00:00') 的日期格式,或者寫個正則轉換ios系統中元素被觸摸時產生的半透明灰色遮罩怎么去掉
<style>a,button,input,textarea{-webkit-tap-highlight-color: rgba(0,0,0,0);} </style>禁止ios長按時觸發系統的菜單,禁止ios&android長按時下載圖片
禁止ios 長按時觸發系統的菜單,禁止ios&android長按時下載圖片 html,body{touch-callout: none;-webkit-touch-callout: none;user-select:none;-webkit-user-select:none; }禁止ios和android用戶選中文字
html,body{user-select:none;-webkit-user-select:none; }安卓部分版本input的placeholder偏上
input{line-height:normal; }ES6面試題
ES6用過那些:
let const 解構賦值、模板字符串、箭頭函數、promise、async await 、class、函數默認值 拓展運算符(...name) map&set數據結構、模塊化語法數組方法: map 如果想要返回一個數組 reduce 如果需要一個結果,比如累加求和 find 找到后立即返回滿足條件的第一個值 findindex 返回索引map&set數據結構 map有key和value set只有value(不允許值重復)filter 過濾一個結果是否存在(可以為空,所以需要判斷) Es5var、let、const區別
var、let、const 共同點都是可以聲明變量的區別一:var 具有變量提升的機制let和const沒有變量提升的機制 區別二:var 可以多次聲明同一個變量let和const不可以多次聲明同一個變量 區別三:var、let聲明變量的const聲明常量var和let聲明的變量可以再次賦值,但是const不可以再次賦值了。 區別四:var聲明的變量沒有自身作用域let和const聲明的變量有自身的作用域作用域考題
考題一:let和const沒有變量提升性
console.log( str );//undefined var str = '你好';console.log( num );//報錯 let num = 10;考題二:
function demo(){var n = 2;if( true ){var n = 1;}console.log( n );//1 } demo();function demo(){let n = 2;if( true ){let n = 1;}console.log( n );//2 } demo();考題三:可以修改
const obj = {a:1 } obj.a = 11111; console.log( obj )const arr = ['a','b','c']; arr[0]= 'aaaaa'; console.log( arr );將下列對象進行合并
方式一:Object.assign
const a = {a:1,b:4}; const b = {b:2,c:3};let obj1 = Object.assign(a,b); console.log( obj1 );方式二:…
let obj2 = {...a,...b}; console.log( obj2 );方式三:自己封裝方法
function extend( target, source ){for(var key in source){target[key] = source[key];}return target; } console.log( extend(a,b) );箭頭函數和普通函數有什么區別?
1. this指向的問題箭頭函數中的this只在箭頭函數定義時就決定的, 箭頭函數繼承來的this指向不會改變(call、apply、bind無效)箭頭函數不能作為構造函數沒有arguments、prototype(call、apply、bind)****箭頭函數的this定義時候、指向外層第一個普通函數的this2. 箭頭函數不能new(不能當作構造函數) 3. 箭頭函數prototype 4. 箭頭函數argumentsPromise有幾種狀態
有三種狀態: pending(進行中) fulfilled(已成功) rejected(已失敗)find和filter的區別
區別一:返回的內容不同filter 返回是新數組find 返回具體的內容 區別二:find :匹配到第一個即返回filter : 返回整體(沒一個匹配到的都返回)some和every的區別
some ==》 如果有一項匹配則返回true every ==》 全部匹配才會返回truefor in 和 for of 的區別?
for..in 用于循環可迭代對象,雖然可以用于字符串和數組,但不建議。for...of 用于用于循環字符串或數組第三章 Vue
Vue 基礎
介紹一下SPA以及SPA有什么缺點?
SPA是什么?單頁面應用 缺點:1. SEO優化不好2. 性能不是特別好3. 首次加載慢多頁面SEO比單頁面SEO好 (方便蜘蛛抓取),收入得多。講一下MVVM
把一個大的網頁拆分成多個組件。
在vue中我們通過插值表達式渲染頁面數據,M就是這個data(model層),v就是這個展示的數據即(view視圖層)。MV 就是數據展示到頁面過程,這個時候是單向的 VM就是理解為v-model原理實現,通過視圖去更新數據雙向綁定原理
什么是響應式數據? 視圖發生修改data中的數據也發生修改。
vue數據雙向綁定原理通過`數據劫持`結合`發布訂閱模式`的方式來實現的。 核心就是使用 Object.defineProperty()劫持數據 的 get/set 監聽數據的變化首先我們要有一個`數據監聽器`,用來劫持并監聽所有屬性,如果改變,就通知訂閱者Watcher。 然后還需要一個`指令解析器`,她用于節點遍歷和重新渲染以及綁定相應的更新函數。 還要實現一個`訂閱者Watcher`,作為數據監聽器和指令解析器的橋梁,數據變化時執行相應函數,從而更新視圖。在使用vue時候,明顯能體驗到一個點: 數據是在data中定義的,然后能直接通過this.xx獲取數據,而且一個修改數據就會互相通知跟著一起改變。所以這里一定不是通過直接賦值和深淺拷貝實現的,而通知的實現就是通過Object.defineProperty()里的get和set方法,監控是獲取還是修改。
什么是虛擬DOM
其實就是數據,把dom變成數據結構。vue的優缺點:
優點:
響應式、組件化、插件化、 響應式 MVVM 一個大網頁可以拆分成多個組件合并成一個大的,利于維護。 只要整理好數據結構,通過數據驅動DOM缺點:
原理還是DOM操作,只是vue有數據驅動, 初次加載耗時多,而且可能會造成重繪,性能沒前后端不分離好。 由于是單頁面應用,不能使用瀏覽器前進后退功能,所有頁面切換切換需要自己建立管理棧。 因為是數據驅動,所以頁面源碼中很少有內容,所以不利于seo。v-if和v-show區別
1. 展示形式不同 v-if是 創建一個dom節點 v-show 是display:none 、 block2. 使用場景不同 初次加載v-if要比v-show好,頁面不會做加載盒子 頻繁切換v-show要比v-if好,創建和刪除的開銷太大了,顯示和隱藏開銷較小v-if和v-for優先級
v-for的優先級要比v-if高 ***是在源碼中體現的:function genElementref是什么?
來獲取dom的nextTick是什么?
獲取更新后的dom內容scoped原理
1. 作用:讓樣式在本組件中生效,不影響其他組件。 2. 原理:給節點新增自定義屬性,然后css根據屬性選擇器添加樣式。Vue中如何做樣式穿透
stylus樣式穿透使用:>>> sass和less使用:/deep/ 通用使用: :v-deepVue組件傳值
父組件-->子組件:1. 父組件:<user-detail :myName="name" />export default {components: {UserDetail}......}2. 在子組件中使用props(可以是數組也可以是對象)接收即可??梢詡鞫鄠€屬性。export default {props: ['myName']}子組件-->父組件:1. 子組件<button @click="changeParentName">改變父組件的name</button>export default {methods: {//子組件的事件changeParentName: function() {this.$emit('handleChange', 'Jack')}}}2. 父組件<child @handleChange="changeName"></child>methods: {changeName(name) { this.name = name}}兄弟組件之間:bus.jsprops和data優先級誰高?
props ===> methods ===> data ===> computed ===>watchcomputed、methods、watch有什么區別?
相同點: 都可以對data數據進行二次修改。
執行問題:computed有緩存,只會執行一次,以后都會走緩存,methods無緩存,所以每次調用都會重新執行。
- computed 計算屬性
- methods 存放方法的
- watch 監聽數據變化
你有碰到或點擊按鈕后頁面數據不更新的問題嗎,怎么解決?
<template><div >{{ obj }}<button @click="btnShow">點擊更新obj</button> </div> </template><script> export default {data() {return {obj: { a: '你好啊',b: '2022'}}},methods: {btnShow() {// this.obj.c = 'fsdfsd' //這樣寫發現點擊無法更新頁面數據this.$set(this.o, 'c', 'liaoyi') // 使用$set 可以完美解決 (點擊就可以更新了)}} } </script>Vue2.x 生命周期
生命周期:組件從創建到銷毀的一個過程,4個階段:創建、掛載、更新、銷毀。
vue的功能都是圍繞生命周期進行的,在周期不同的階段調用對應的鉤子函數,實現組件數據的管理和DOM的渲染
4461
1. 有哪些生命周期系統自帶: 創建前后:beforeCreate → 可以加loading事件created → 發起異步請求、結束loading事件 掛載前后:beforeMountmounted → 操作DOM、發送請求 更新前后: beforeUpdate → 可以在這里訪問dom,刪除一些事件監聽器updated 銷毀前后: beforeDestroy 銷毀前,刪除一些提示destroyed2. 一旦進入到頁面或者組件,會執行哪些生命周期,順序。beforeCreate、created、beforeMount、mounted3. 在哪個階段有$el,在哪個階段有$databeforeCreate 啥也沒有created 有data沒有elbeforeMount 有data沒有elmounted 都有4. 如果加入了keep-alive會多倆個生命周期activated、deactivated5. 如果加入了keep-alive,第一次進入組件會執行哪些生命?第一次:beforeCreatecreatedbeforeMountmountedactivated 6. 如果加入了keep-alive,第二次或者第N次進入組件會執行哪些生命周期?只執行一個生命周期: 第二次或第N次 activated你在什么情況下用過哪些生命周期?
項目中使用最多的就是 created、mounted
created ==》 請求接口 (因為有data沒有el,mounted會造成重繪或回流) mounted ==》 獲取DOM(做效果,獲取dom的高度,用插件)其他問題:鏈接:https://pan.baidu.com/s/1Uo-jUGyxBlYDwjRadtnBWQ 密碼:tr5c
談談你對keep-alive的了解
1. 是什么 vue系統自帶的一個組件,功能:是來緩存組件的。===》提升性能 2. 使用場景 就是來緩存組件,提升項目的性能。具體實現比如:首頁進入到詳情頁,如果用戶在首頁每次點擊都是相同的,那么詳情頁就沒必要請求N次了,直接緩存起來就可以了,當然如果點擊的不是同一個,那么就直接請求。vue-router
路由模式:
history http://localhost:8080/mine hash http://localhost:8080#/mine1. 樣式不同2. 請求 如果在找不到對應這個路由的情況下 (比如在鏈接后面隨便輸入了東西, 解決:可以配置404頁面)history會發送一次get請求、hash不會發送3.打包后前端環境自測history無內容(空白頁),hash有內容。路由跳轉
push 跳轉并新增一條歷史記錄 replace 替換掉當前頁面,并替換掉當前的歷史記錄 go(n) 瀏覽歷史中前進和后退 back() 后退到上一個頁面 forward() 前進到下一個頁面路由傳值
有兩種傳值方式: 一個是通過query顯示傳值, 一個是通過參數params隱式傳值。 因為使用隱式傳值跳轉刷新界面后參數問題無法解決,所以路徑傳值一定是顯示的。 1. 顯式 ==> 參數在url上http://localhost:8080/about?a=1傳:this.$router.push({path:'/about',query:{a:1}})接:this.$route.query.a2. 隱式 ==> 參數不在url上http://localhost:8080/about傳:this.$router.push({name:'About', //傳nameparams:{a:1}})接:this.$route.params.a路由導航守衛
全局、路由獨享、組件內 1. 全局beforeEach、beforeResolve、afterEach2. 路由獨享beforeEnter 在路由vue-router配置的路由單獨設置 beforeEnter(){}3. 組件內 - 不好維護,一般不用beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave使用場景:判斷是否登錄,如果登錄就next否則就跳轉到登錄頁面子路由、路由嵌套、動態路由
子路由: 好維護,不用一直新建一級路由 動態路由: 值路由很多(999+),這時候使用動態路由方便比如商城的商品點擊詳情頁數據的渲染 -> 首頁傳id,詳情頁接收id,在請求id
使用動態路由: http://localhost:8080/detail/123323?*** 首頁傳id,
不使用動態路由: http://localhost:8080/detail
Vuex
什么時候用vuex,什么時候用 modules ?
什么時候用vuex?1. 傳值復雜 2. 數據多,需要更好的去管理數據(方便,項目好維護)什么時候用 modules? modules是為了把項目再次細分,方便后期維護 【例如:商城項目有很多state】, 購物車,我的,訂單管理,地址管理...為了更好的維護和管理,采用modulesVuex有哪些屬性?
state、getters、mutations、actions、modulesstate 存放數據,類似于組件的data getters 計算屬性,類似于組件的computed mutations 存放方法,類似于組件的methodsactions 存放方法,用于提交mutations,不建議是直接在actions中寫入方法,actions可以包含異步操作(這個是mutaitons做不了的)modules 把以上4個屬性再細分,讓倉庫更好管理Vuex是單向數據流還是雙向數據流?
Vuex是單向數據流 不能直接修改vuex的數據,只能在mutaitons中更改。組件使用vuex數據直接修改會報錯,那么mutations不會報錯為什么?
因為是vuex是單向數據流Vuex中的mutaitons和actions區別
mutaitons : 必須是同步函數 actions : 可以包含任意異步操作使用的時候,方法就寫在mutations中(邏輯)。 actions是來提交mutaitons的,不建議直接在actions里面寫Vuex如何做持久化存儲
如果在組件修改了vuex的數據,刷新頁面為什么會到之前沒有修改過的值?
因為Vuex本身不是持久化存儲:1. 使用localStorage、 自己寫cookie 但是cookie需要環境,指向域名或ip地址。2. 使用vuex-persist 插件( 這個插件的原理也是localStorage) vuex 存儲的數據雖然是響應式的。但是并不會保存起來,刷新之后就回到了初始狀態,具體做法應該在vuex里數據改變的時候把數據拷貝一份保存到localStorage里面,刷新之后,如果localStorage里有保存的數據,取出來再替換store里的state。配置和打包上線
vue打包成多頁面使用插件 : prerender-spa-plugin項目打包時遇到的問題:
***打包出現空白頁
解決:1. 打包后路徑問題 : (run build)默認在電腦的根目錄查找module.exports = {publicPath:'./', //改為當前根目錄}2. 內容不顯示【路由問題】路由切換無法加載這時候前端想要正常切換頁面,路由模式修改成hash模式即可(#)【后端】打包后如果要是history模式,需要后端做重定向3. 如果是代理請求的數據,打包后不生效你有沒有配置過代理 ?
vue中的代理是來解決跨域的問題的! 注意:代理在生產環境不生效(axios的url寫的是什么,就是什么,不用代理的前綴)解決開發前配置了代理 打包后不生效問題
在項目根目錄 新建 .env.development、.env.production配置文件
? .env.development ==>開發環境
# 頁面標題 VUE_APP_TITLE = 開發環境 # 開發環境配置 VUE_APP_ENV = 'development' # 開發環境代理 VUE_APP_BASE_API = 'http://localhost:3000'? .env.production ===>生產環境
# 頁面標題 VUE_APP_TITLE = 生產環境 # 生產環境配置 VUE_APP_ENV = 'production' # 生產環境代理 VUE_APP_BASE_API = 'http://localhost:3000'開發和打包的時候會vue自動找這個配置文件。
后臺搭建和跨域解決
一、搭建后端目錄
全局命令:npm install express-generator -g 進入項目目錄:express --view=ejs server二、node — express 跨域
router.all('*', function (req, res, next) {res.header('Access-Control-Allow-Origin', '*');res.header('Access-Control-Allow-Headers', 'Content-Type');res.header('Access-Control-Allow-Methods', '*');res.header('Content-Type', 'application/json;charset=utf-8');next(); });微信小程序面試題
如何自定義頭部?
app.json進行配置"window":{"navigationStyle":"custom", }如何自定義底部?
不校驗URL
工具==》詳情==》本地設置==》不校驗合法域名 : 項目上線前URL一定要請求到(不勾選也可以請求到數據)uni-app面試題
生命周期
應用生命周期、頁面生命周期、組件生命周期條件編譯
在工具中,打if出現的條件編譯例如: <!-- #ifdef H5 --><h1>這是h5端</h1> <!-- #endif -->性能優化篇
加載優化
1. http請求能不能減少(能不能合并) 2. 圖片的雪碧圖 3. script標簽位置 4. link標簽(css引入)圖片優化
1. 圖片懶加載 2. 響應式圖片 (如果是開發響應式網站) 3. webp代替其他格式 4. 小圖標可以改用字體圖標渲染優化
1. 減少重繪和回流 2. 改變位置使用transform 3. 動畫盡量用requestAnimationFrame,不要用定時器首屏優化
計算首屏加載時間: (performance.timing,domComplete - performance.timing.navigationStart) / 1000 1. 長列表 (1000條數據,如何展示到頁面上) 2. 項目的html文件、css文件、圖片、js文件壓縮打包vue優化
1. keep-alive 緩存組件 2. 路由懶加載 3. 方法的正確使用v-if和v-showcomputed、watch、methodsv-for循環的時候,盡量別用index,而是用id 4. Object.freeze :凍結對象純展示類的接口數據,凍結就可以了 5. 使用ui組件按需引入webpack面試題
webpack是一個模塊打包工具,用于管理項目模塊依賴,并編譯出所需的靜態資源。
功能:
代碼轉換: ts編譯成js,scss編譯成css文件優化: 壓縮代碼、圖片代碼分割: 提取多頁面的公共代碼,比如提取首頁不需要執行部分的代碼讓它異步加載。代碼校驗、自動發布。 file/ css/ style / less / ts / babel-loader mini-css-extaact-plugin 提取css為單獨文件 clean-webpack-plugin 目錄清理 copy-webpack-plugin 拷貝文件 webpack-bundle-analyzer 可視化輸出打包后各文件大小Git面試題
分布式代碼托管平臺
分布式:大家可以提交代碼, (本地也有暫存區,即使斷網了也可以運行git add . 和 git commit先提交到本地)。
git常用命令
git init 初始化倉庫(生成.git文件夾--隱藏文件夾) git config -l 查看配置 (配置的用戶名,郵箱、可以用來追溯是誰提交的代碼) git status 查看狀態 (標記為紅色說明文件沒有被git管理,需要把文件添加到暫存區,綠色說明已被管理)git add . 把當前項目所有文件添加到暫存區 (讓git接管當前項目的文件) git add index.js 指定文件上傳到暫存區git diff 查看修改的文件 git log 查看修改歷史(詳細輸出,誰修改的,幾點修改,以及提交時間) git reflog 查看修改歷史(簡單輸出,只輸出提交了幾次和修改的文件)回到之前的版本: git reset --hard HEAD^ git reset --hard 版本號 回到指定版本 ( 執行git reflog 最開頭的[f781dee] 就是版本號)git commit -m '備注內容' 添加到分支中 (默認添加到master主分支) git push 推送到云端分支的操作:***默認的主分支 : master git branch (查看本地分支) git branch 分支名稱 (新建分支) git checkout 分支名稱 (切換分支) 如何查看遠程倉庫的分支 git branch -r git push --set-upstream origin 分支名稱 (本地分支提交到遠程倉庫) git branch -d 分支名稱 (刪除本地分支)如何刪除遠程倉庫的分支 git push origin --delete 分支名稱解決沖突
git push為什么報錯?
如果遠程倉庫有人更新了代碼,那我們不能直接 git push 解決: 必須先拉取遠程倉庫的代碼(執行 git pull ),然后再push但是,有的時候還是會出現問題,多人同時修改了一個文件,導致代碼沖突,后一個人提交時報錯:
后提交的人解決問題:手動解決沖突代碼,協商保留或者刪除。
工作中應該寫一個模塊就提交,避免自己碰到代碼沖突!。
跨域面試題
前端:會碰到jsonp跨域問題、vue的項目可以設置代理(打包后無效。解決:.ENV文件) 后端:CORShttp和https的區別?
1. 端口不同http :80端口https :443端口2. https比http更加安全***https就是證書token
token是后端生成的token + cookie : 前端判斷是否過期 token + localStorage : 后端判斷是否過期給前端返回code碼,前端判斷code碼等于多少SEO - 搜索引擎優化
1. 網站一定要多頁面 2. title、描述、關鍵字 3. 圖片、音頻、視頻、的標簽屬性特別關鍵 4. 網站不能出現死鏈接前端常用工具庫:
nanoid 生成唯一標識
nanoid庫和uuid庫一樣都可以生成uuid,但是nanoid相比uuid要更輕量級。
npm i nanoid -S import {nanoid} from 'nanoid' 直接調用nanoid(),即可生成一個uuidVue-Lazyload 圖片懶加載
圖片懶加載,添加自定義指令。
cnpm i vue-lazyload -S import VueLazyload from 'vue-lazyload'// 傳入一個配置對象,設置懶加載默認的 loading圖片 Vue.use(VueLazyload, {loading: require('@/assets/images/loding.gif'), })在組件中使用: :src 替換成 v-lazy 即可vee-validate 表單驗證插件
下載:高版本問題太多,建議下載指定版本
cnpm i vee-validate@2 -S使用插件:
避免 main.js 雜亂,我們在src目錄新建 plugins/validate.js 文件
在mian.js引入:
import "@/plugins/validate"; //引入表單校驗插件編寫 validate.js 文件:
import Vue from "vue"; import VeeValidate from "vee-validate"; import zh_CN from "vee-validate/dist/locale/zh_CN"; //中文提示信息 Vue.use(VeeValidate);// 表單驗證和設置提示信息 VeeValidate.Validator.localize('zh_CN', {messages: {...zh_CN.messages,is: (field) => `${field}必須與密碼相同` // 修改內置規則的 message,讓確認密碼和密碼相同},attributes: { // 給校驗的 field 屬性名映射中文名稱phone: '手機號',code: '驗證碼',password:'密碼',password1:'確認密碼',isCheck:'協議'} })//自定義校驗規則 (協議必須打勾同意) VeeValidate.Validator.extend('agree', {validate: value => {return value},getMessage: field => field + '必須同意' })在組件中使用
第三步:基本使用 <inputplaceholder="請輸入你的手機號"v-model="phone"name="phone"v-validate="{ required: true, regex: /^1\d{10}$/ }":class="{ invalid: errors.has('phone') }"/> <span class="error-msg">{{ errors.first("phone") }}</span>點擊按鈕提交:
const success = await this.$validator.validateAll(); //保證全部表單驗證成功后才發請求總結
以上是生活随笔為你收集整理的前端面试题总结-初级的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue开发常用css,js(持续更新)
- 下一篇: uniapp的checkbox标签属性