記2019的一次面試

前端小兵發表於2019-03-07

CSS3常用屬性

  • border-radius 圓角
  • box-shadow 陰影:X軸偏移值 Y軸偏移值 X軸陰影模糊半徑 Y軸陰影模糊半徑 陰影顏色
  • box-sizing 定義盒模型
    • 屬性值為content-box時,寬高的值為content的寬高
    • 屬性值為border-box時, 寬高的值為border+padding+content也就是整個盒模型的寬高;
  • linear-gradient 背景顏色線性漸變
  • radial-gradient 背景顏色徑向漸變
  • text-shadow 文字陰影
  • background-size 設定背景影像的高度和寬度
  • @keyframs 動畫名稱 定義動畫序列
  • animation: 1s keyname infinite 時間 動畫名 次數
  • transform 變換

display有哪些屬性,作用

  • none 元素不顯示
  • block 顯示為塊級元素
  • inline 顯示為內聯元素
  • inline-block 行內塊元素
  • flex 設定為伸縮盒子
  • inherit 從父元素繼承 display 屬性的值

CSS實現垂直水平居中

  • 定位方式
1. absolute + 負margin
.father {
    position: relative,
}
.son {
    position: absolute;
    width: 50px;
    height: 50px;
    margin-top: -25px;
    margin-left: -25px;
}
2. absolute + margin auto
.father {
    position: relative,
}
.son {
    position: absolute;;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}
3. absolute + transform
.father {
    position: relative,
}
.son {
    position: absolute;;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
複製程式碼
  • flex方式
.father {
    display: flex;
    justify-content: center;
    align-items: center;
}
複製程式碼
  • grid方式
.father {
    display: grid;
}
.son {
    aligin-self: center;
    justify-self: center;
}
複製程式碼

物件的淺拷貝和深拷貝,有哪些實現方式。

  • JS 中的淺拷貝與深拷貝,只是針對複雜資料型別(Object,Array)的複製問題。淺拷貝與深拷貝都可以實現在已有物件上再生出一份的作用。但是物件的例項是儲存在堆記憶體中然後通過一個引用值去操作物件,由此拷貝的時候就存在兩種情況了:拷貝引用和拷貝例項,這也是淺拷貝和深拷貝的區別。

  • 淺拷貝: 淺拷貝是拷貝引用,拷貝後的引用都是指向同一個物件的例項,彼此之間的操作會互相影響

  • 淺拷貝實現方式

  • 1.拷貝原物件的引用

var a = {c:1};
var b = a;
console.log(a === b); // 輸出true。
a.c = 2;
console.log(b.c); // 輸出 2
複製程式碼
  • 2.源物件拷貝例項,其屬性物件拷貝引用
    • 這種情況,外層源物件是拷貝例項,如果其屬性元素為複雜雜資料型別時,內層元素拷貝引用。 對源物件直接操作,不影響另外一個物件,但是對其屬性操作時候,會改變另外一個物件的屬性;常用方法為:Array.prototype.slice(), Array.prototype.concat(), jQury的$.extend({},obj)
var a = [{c:1}, {d:2}];
var b = a.slice();
console.log(a === b); // 輸出false,說明外層陣列拷貝的是例項
a[0].c = 3;
console.log(b[0].c); // 輸出 3,說明其元素拷貝的是引用
複製程式碼
  • Object.assign()實現物件的淺拷貝
  • 深拷貝: 在堆中重新分配記憶體,並且把源物件所有屬性都進行新建拷貝,以保證深拷貝的物件的引用圖不包含任何原有物件或物件圖上的任何物件,拷貝後的物件與原來的物件是完全隔離,互不影響。
    • 實現方式:
      • JSON.stringify(),JSON.parse()
      • 使用Object.create()的方法
      • jQury的$.extend(true,{},obj)
  • ...展開運算子實現淺拷貝

陣列常用的方法,哪些會改變陣列哪些不會

  • Array.from()從一個類似陣列或可迭代物件中建立一個新的陣列例項

  • Array.isArray()用於確定傳遞的值是否是一個 Array

  • Array.concat()(不會更改原陣列)方法用於合併兩個或多個陣列。此方法不會更改現有陣列,而是返回一個新陣列。

  • Array.every測試陣列的所有元素是否都通過了指定函式的測試

  • Array.filter()(不會更改原陣列)建立一個新陣列, 其包含通過所提供函式實現的測試的所有元素

  • Array.find()返回陣列中滿足提供的測試函式的第一個元素的值。否則返回 undefined。

  • Array.findIndex()返回陣列中滿足提供的測試函式的第一個元素的索引 ected output: 3

  • Array.includes()判斷一個陣列是否包含一個指定的值,根據情況,如果包含則返回 true,否則返回false。

  • Array.indexOf()方法返回在陣列中可以找到一個給定元素的第一個索引,如果不存在,則返回-1

  • Array.join()將一個陣列(或一個類陣列物件)的所有元素連線成一個字串並返回這個字串。如果陣列只有一個專案,那麼將返回該專案而不使用分隔符。

  • Array.pop()(改變原陣列)從陣列中刪除最後一個元素,並返回該元素的值

  • Array.push()(改變原陣列)將一個或多個元素新增到陣列的末尾,並返回該陣列的新長度

  • Array.reduce()對陣列中的每個元素執行一個由您提供的reducer函式(升序執行),將其結果彙總為單個返回值。

  • Array.reverse()將陣列中元素的位置顛倒,第一個陣列元素成為最後一個陣列元素,最後一個陣列元素成為第一個。

  • Array.shift()(改變原陣列)從陣列中刪除第一個元素,並返回該元素的值。

  • Array.unshift()(改變原陣列)將一個或多個元素新增到陣列的開頭,並返回該陣列的新長度。

  • Array.slice()(不改變原陣列)方法返回一個新的陣列物件,這一物件是一個由 begin和 end(不包括end)決定的原陣列的淺拷貝

  • Array.sort()用原地演算法對陣列的元素進行排序,並返回陣列。排序演算法現在是穩定的

Array.splice()(改變原陣列)

  • 方法通過刪除現有元素和/或新增新元素來修改陣列,並以陣列返回原陣列中被修改的內容
var months = ['Jan', 'March', 'April', 'June'];
months.splice(1, 0, 'Feb');
// inserts at 1st index position
console.log(months);
// expected output: Array ['Jan', 'Feb', 'March', 'April', 'June']

months.splice(4, 1, 'May');
// replaces 1 element at 4th index
console.log(months);
// expected output: Array ['Jan', 'Feb', 'March', 'April', 'May']
複製程式碼

this指向的問題

  • this是執行時繫結的,所以取決於函式的執行上下文
  • 當一個函式被呼叫時,會建立一個活動記錄(執行上下文)。這個記錄會包含函式在哪裡被呼叫(呼叫棧)、函式的呼叫方法、傳入的引數等資訊,this也是這裡的一個屬性。
  • 1.獨立函式呼叫 這種直接呼叫的方式this指向全域性物件,如果是在瀏覽器就指向window
function foo(){
    console.log(this.a)
}
var a = 2
foo()  // 2
複製程式碼
  • 2.物件上下文(隱試繫結)
function foo() { 
    console.log( this.a );
}
var obj = { 
    a: 2,
    foo: foo
};
obj.foo(); // 2
複製程式碼
  • foo雖然被定義在全域性作用域,但是呼叫的時候是通過obj上下文引用的,可以理解為在foo呼叫的那一刻它被obj物件擁有。所以this指向obj
  • 3.顯式繫結 通過call、apply、bind顯式地更改this指向。
  • 4.new繫結 “建構函式”和原型中的this永遠指向new出來的例項
  • 5.箭頭函式中的this 而是“繼承”外層作用域中的this指向 箭頭函式不改變this的指向

Vue的常用指令

  • 指令都是行內屬性
  • v-model放在input、textarea、select>option上的,實現雙向資料繫結
  • v-text 展示對應的文字
  • v-once 對應的標籤只渲染一次
  • v-show=布林 是否能顯示,true能顯示,false不能顯示(存在隱式轉化)
  • v-html 把值中的標籤渲染出來
  • v-for 迴圈顯示元素 可以迴圈陣列、物件、數字、字串 最好加:key='a+i'
  • v-bind 用於繫結行內屬性 簡寫成:
  • v-if 控制是否渲染該元素 值是true,則渲染該元素;false則不渲染 與v-else v-else-if連著使用 可以使用template標籤,就不會出現多餘標籤

Vue的v-if和v-show的區別

  • v-showv-if都是用來顯示隱藏元素,v-if還有一個v-else配合使用
  • v-show
    • 不管條件是真還是假,第一次渲染的時候都會編譯出來,也就是標籤都會新增到DOM中。之後切換的時候,通過display: none;樣式來顯示隱藏元素。可以說只是改變css的樣式,幾乎不會影響什麼效能。
  • v-if
    • 在首次渲染的時候,如果條件為假,什麼也不操作,頁面當作沒有這些元素。當條件為真的時候,開始區域性編譯,動態的向DOM元素裡面新增元素。當條件從真變為假的時候,開始區域性編譯,解除安裝這些元素,也就是刪除。
  • 效能方面
    • v-if絕對是更消耗效能的,因為v-if在顯示隱藏過程中有DOM的新增和刪除,v-show就簡單多了,只是操作css。

Vue雙向資料繫結的原理

微信小程式開發中遇到的問題

  • 小程式不支援background使用本體圖片,只能使用base64圖片,或者是用網路圖片; 可以使用字型圖示等。
  • 定義事件無法傳值,在元件上定義自定義屬性 通過event.currentTarget.dataset

jquery遍歷的方法,jquery時間繫結怎麼做

  • 便利方法$()
  • bind()函式只能針對已經存在的元素進行事件的設定;但是live(),on(),delegate()均支援未來新新增元素的事件設定;
  • on()方法可以繫結動態新增到頁面元素的事件,on()方法繫結事件可以提升效率

js實現非同步的方式,詳細講解ES發展實現非同步的途徑

前端安全性措施

  • 防止XSS攻擊(跨網站指令碼),
    • 是一種網站應用程式的安全漏洞攻擊,是程式碼注入的一種
    • 防禦:轉義控制使用者輸入輸出的內容,對於引號,尖括號,斜槓進行轉義。
  • 採用CSP(內容安全策略)
    • 用於檢測並削弱某些特定型別的攻擊,包括跨站指令碼 (XSS) 和資料注入攻擊等。無論是資料盜取、網站內容汙染還是散發惡意軟體,這些攻擊都是主要的手段。
    • 通過 HTTP Header 中的 Content-Security-Policy 來開啟 CSP
    • 只允許載入本站資源Content-Security-Policy: default-src ‘self’
    • 只允許載入 HTTPS 協議圖片Content-Security-Policy: img-src https://*
  • 防止CSRF(跨站請求偽造)
    • 利用使用者的登入態發起惡意請求
    • 防禦:
      • Get 請求不對資料進行修改
      • 不讓第三方網站訪問到使用者 Cookie
      • 阻止第三方網站請求介面
      • 請求時附帶驗證資訊,比如驗證碼或者 token
  • 對密碼加鹽,然後進行幾次不同加密演算法的加密。
// 加鹽也就是給原密碼新增字串,增加原密碼長度
sha256(sha1(md5(salt + password + salt)))
複製程式碼

前端效能優化

選擇合適的快取策略

  • 對於某些不需要快取的資源,可以使用Cache-control: no-store ,表示該資源不需要快取。
  • 對於頻繁變動的資源,可以使用Cache-Control: no-cache 並配合 ETag 使用,表示該資源已被快取,但是每次都會傳送請求詢問資源是否更新。
  • 對於程式碼檔案來說,通常使用 Cache-Control: max-age=31536000 並配合策略快取使用,然後對檔案進行指紋處理,一旦檔名變動就會立刻下載新的檔案。

使用HTTP2.0

  • 在 HTTP / 2.0 中引入了多路複用,能夠讓多個請求使用同一個 TCP 連結,極大的加快了網頁的載入速度。並且還支援 Header 壓縮,進一步的減少了請求的資料大小

預載入

  • 資源不需要馬上用到,但是希望儘早獲取,這時候就可以使用預載入。預載入其實是宣告式的 fetch ,強制瀏覽器請求資源,並且不會阻塞 onload 事件,可以使用以下程式碼開啟預載入
<link rel="preload" href="http://example.com" />
複製程式碼

靜態資源使用CDN載入

  • 靜態資源儘量使用 CDN 載入,由於瀏覽器對於單個域名有併發請求上限,可以考慮使用多個 CDN 域名。對於 CDN 載入靜態資源需要注意 CDN 域名要與主站不同,否則每次請求都會帶上主站的 Cookie。

優化渲染過程

懶載入

  • 懶載入的原理就是隻載入自定義區域(通常是可視區域,但也可以是即將進入可視區域)內需要載入的東西。對於圖片來說,先設定圖片標籤的 src 屬性為一張佔點陣圖,將真實的圖片資源放入一個自定義屬性中,當進入自定義區域時,就將自定義屬性替換為 src 屬性,這樣圖片就會去下載資源,實現了圖片懶載入
  • 懶載入不僅可以用於圖片,也可以使用在別的資源上。比如進入可視區域才開始播放視訊等等。

圖片載入優化

  • 不用圖片。很多時候會使用到很多修飾類圖片,其實這類修飾圖片完全可以用 CSS 去代替
  • 對於移動端來說,螢幕寬度就那麼點,完全沒有必要去載入原圖浪費頻寬。一般圖片都用 CDN 載入,可以計算出適配螢幕的寬度,然後去請求相應裁剪好的圖片
  • 小圖使用 base64 格式
  • 將多個圖示檔案整合到一張圖片中(雪碧圖)
  • 選擇正確的圖片格式:
    • 對於能夠顯示 WebP 格式的瀏覽器儘量使用 WebP 格式。因為 WebP 格式具有更好的影像資料壓縮演算法,能帶來更小的圖片體積,而且擁有肉眼識別無差異的影像質量,缺點就是相容性並不好
    • 小圖使用 PNG,其實對於大部分圖示這類圖片,完全可以使用 SVG 代替
    • 照片使用 JPEG

伺服器端開啟GZIP壓縮

webpack編譯打包時間的優化

  • 元件按需引入,藉助外掛babel-plugin-import實現按需載入元件,減少檔案體積,修改.babelrc檔案。
  • 啟用happypack多程式構建專案:happypack 的原理是讓loader可以多程式去處理檔案,它把任務分解給多個子程式去併發的執行,子程式處理完後再把結果傳送給主程式
  • 修改source-map配置
  • 啟用DllPlugin和DllReferencePlugin預編譯庫檔案

Hybrid app 原生和H5通訊

設計模式有哪些

  • 設計模式的定義:在物件導向軟體設計過程中針對特定問題的簡潔而優雅的解決方案

單體模式:

  • 單體模式思想在於保證一個特定類僅有一個例項,意味著當你第二次使用同一個類建立信物件時,應得到和第一次建立物件完全相同。

工廠模式:

  • 工廠模式是為了建立物件。

中介者模式

  • 通過一箇中介者物件,其他所有的相關物件都通過該中介者物件來通訊,而不是相互引用,當其中的一個物件發生改變時,只需要通知中介者物件即可。通過中介者模式可以解除物件與物件之間的緊耦合關係。
  • 中介者模式適用的場景:例如購物車需求,存在商品選擇表單、顏色選擇表單、購買數量表單等等,都會觸發change事件,那麼可以通過中介者來轉發處理這些事件,實現各個事件間的解耦,僅僅維護中介者物件即可。

觀察者模式

  • 觀察者模式( 又叫釋出者-訂閱者模式 )應該是最常用的模式之一. 在很多語言裡都得到大量應用.
  • 包括我們平時接觸的dom事件. 也是js和dom之間實現的一種觀察者模式.只要訂閱了div的click事件. 當點選div的時候, function click就會被觸發.

代理模式

  • 通過包裝一個物件從而控制對它的訪問,其中主要方法是將方位聚集為租或者 僅當真正必要時侯才執行訪問,從未避免高昂的操作開銷。

相關文章