記2018前端面試之旅

持續更新直到找到合適工做爲止!-_-!javascript

面試一

日期:20180420css

前端性能優化?

前端性能優化這個問題能夠回答的比較多,我本身的答案:
前端性能優化能夠從:html

  • 減小HTTP請求的數量
  • 減小HTTP請求的大小
  • 緩存
  • 內容分發網絡
  • 腳本放置在底部,樣式表放置在頂部
  • ...

減小HTTP請求的數量:前端

  • 將公用的js、css文件合併
  • CSS雪碧圖
  • 圖片地圖
  • 內聯圖片

不詳細贅述了vue

標題文字

圖片預加載方式?

圖片預加載的主要思路: 圖片預加載的主要思路就是把稍後須要用到的圖片悄悄的提早加載到本地,由於瀏覽器有緩存的緣由,若是稍後用到這個url的圖片了,瀏覽器會優先從本地緩存找該url對應的圖片,若是圖片沒過時的話,就使用這個圖片。html5

圖片預加載實現的方法:java

  • 適用js的image對象也有onload和onerror事件,分別是加載完後和加載失敗時執行。

Image對象是專門用於處理圖片加載的,就至關於內存中的img標籤。react

  • css實現圖片預加載:寫一個CSS樣式設置一批背景圖片,而後將其隱藏,這樣你就看不到那些圖片了。那些背景圖片就是你想預載的圖片
  • 使用Ajax實現預加載:該方法利用DOM,不只僅預加載圖片,還會預加載CSS、JavaScript等相關的東西。使用Ajax,比直接使用JavaScript,優越之處在於JavaScript和CSS的加載不會影響到當前頁面。該方法簡潔、高效。
  • 使用jQuery圖片預加載(延遲加載)插件Lazy Load:Lazy Load也叫惰性加載,延遲加載,顧名思義,就是在圖片未到達可視區域時,不加載圖片

參考: 圖片預加載的方法git

手寫http請求?(XMLHttpRequest)

使用XMLHttpRequest對象:建立XHR對象、配置header、發送請求!經過設置回調來接受服務器響應!面試

談談promise?

Promise的優勢:

  • 最大的好處是在異步執行的流程中,把執行代碼和處理結果的代碼清晰地分離了
  • 串行執行異步任務,不用Promise須要寫一層一層的嵌套代碼,任何任務失敗則再也不繼續並執行錯誤處理函數
  • Promise還能夠並行執行異步任務

若是咱們組合使用Promise,就能夠把不少異步任務以並行和串行的方式組合起來執行。

ES5做用域和ES6做用域?

ES5: 函數做用域(局部)和全局做用域
ES6: 多出了一個塊級做用域,也就是{}花括號裏聲明的單獨的做用域

ES5怎麼實現類?

使用原型繼承的方式實現類!

對象的深拷貝?ES六、ES5

淺拷貝: 將原對象或原數組的引用直接賦給新對象,新數組,新對象/數組只是原對象的一個引用
深拷貝: 建立一個新的對象和數組,將原對象的各項屬性的「值」(數組的全部元素)拷貝過來,是「值」而不是「引用」

深拷貝對象(不討論數組的狀況):

  • 循環遍歷對象的屬性賦值
  • ES6的Object.assign: (用於對象的合併,將源對象(source)的全部可枚舉屬性,複製到目標對象(target),並返回合併後的target)
  • ES6擴展運算符:擴展運算符(...)用於取出參數對象的全部可遍歷屬性,拷貝到當前對象之中
  • JSON.parse(JSON.stringify(obj)): 上面三種方法不能拷貝全部層級,該方法能夠拷貝對象全部層級
  • 手動些遞歸(-_-!)

參考:https://www.cnblogs.com/pengh...

字符串的截取兩個方法(subString subStr)的區別?

stringObject.substr(start,length):在字符串中抽取從 start 下標開始的指定數目的字符
stringObject.substring(start,stop): 用於提取字符串中介於兩個指定下標之間的字符

使用過less、sass麼?

沒用過,從預編譯語言的優勢回答的
使用的優勢:

  • 方便CSS的維護,成本和編寫成本
  • 爲 CSS 加入程序式語言的特性

缺點:

  • 提升了門檻

跨域?

同源指的是:URL由協議、域名、端口和路徑組成,若是兩個URL的協議、域名和端口相同,則表示他們同源。
同源策略:瀏覽器的同源策略,限制了來自不一樣源的"document"或腳本,對當前"document"讀取或設置某些屬性(可是容許當前源執行其餘源的腳本)

前端跨域實現方式:

  • JSONP:<script> 標籤是不受同源策略的限制的,它能夠載入任意地方的 JavaScript 文件,而並不要求同源。
  • 修改document.domain: 瀏覽器腳本修改document.domain。域名只容許往上升,例如a.git.com到git.com,這樣腳本就能夠訪問git.com上的資源了。還有種用法是假設瀏覽器訪問了a.git.com和b.git.com,若是它們的腳本都把域名設爲git.com,那麼瀏覽器本地的資源能夠共享。
  • window.postMessage:Html5的新方法,兩個域下的腳本能夠跨window通訊。
  • 利用表單:瀏覽器裏不由止表單跨域,因此能夠用Javascript + iframe + 表單實現跨域調用

服務端跨域實現方式:

  • 反向代理服務器: 將你的服務器配置成 須要跨域獲取的資源的 反向代理服務器。也就是說,將其餘域名的資源映射到你本身的域名之下,這樣瀏覽器就認爲他們是同源的。
  • Cross-Origin Resource Sharing: 是 W3C 推出的一種跨站資源獲取的機制。服務器 在響應頭中設置相應的選項,瀏覽器若是支持這種方法的話就會將這種跨站資源請求視爲合法,進而獲取資源。

this 值?

this值在四種狀況下:

  • 全局調用函數時,在ES5中爲指向window對象,但在ES6中this的值爲undefined
  • 對象調用方法時,this的值爲指向該對象
  • 構造函數建立對象時,this指向新建立的對象
  • call/apply/bind 方法時this值被更改成它們三的第一個參數

談談CommonJs、AMD、CMD?

CommonJs: 模塊的加載方式是同步的(服務器端模塊加載)
AMD: 異步方式加載模塊,模塊的加載不影響它後面語句的運行。全部依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成以後,這個回調函數纔會運行。(瀏覽器端模塊加載) AMD的方式比較適合瀏覽器(require.js 遵循的是AMD規範實現的模塊加載)
CMD: CMD至關於按需加載,定義一個模塊的時候不須要當即制定依賴模塊,在須要的時候require就能夠了,比較方便;而AMD則相反,定義模塊的時候須要制定依賴模塊,並以形參的方式引入factory中

AMD 與 CMD 的區別:

  • AMD推崇依賴前置,在定義模塊的時候就要聲明其依賴的模塊
  • CMD推崇就近依賴,只有在用到某個模塊的時候再去require

一樣都是異步加載模塊,AMD在加載模塊完成後就會執行改模塊,全部模塊都加載執行完後會進入require的回調函數,執行主邏輯,這樣的效果就是依賴模塊的執行順序和書寫順序不必定一致,看網絡速度,哪一個先下載下來,哪一個先執行,可是主邏輯必定在全部依賴加載完成後才執行

CMD加載完某個依賴模塊後並不執行,只是下載而已,在全部依賴模塊加載完成後進入主邏輯,遇到require語句的時候才執行對應的模塊,這樣模塊的執行順序和書寫順序是徹底一致的

這也是不少人說AMD用戶體驗好,由於沒有延遲,依賴模塊提早執行了,CMD性能好,由於只有用戶須要的時候才執行的緣由

require.js 遵循AMD規範,主要爲了解決下面兩個問題:

  • 實現js文件的異步加載,避免網頁失去響應
  • 管理模塊之間的依賴性,便於代碼的編寫和維護

參考: http://www.ruanyifeng.com/blo... https://www.jianshu.com/p/042...

vue 中的 data爲何是函數而不是屬性值?

面試二

看代碼說出打印值?

這道題的代碼具體不清了,考查的是數組相似下面這樣

var a = [,1],
    b = [,1,,1],
    c = [1,];
    console.log(a.length); 
    console.log(b.length);
    console.log(c.length);

打印: 2 2 1

如下哪些方法屬於全局函數?在window對象下

A eval
B parseFloat
C setTimeout
D alert
E enscape

clipboard.png

答案: ABCDE

下面哪段代碼會報錯?

A var a = ()
B var b = {}
C var c = []
D var d =

答案: A

如下哪些方法能夠在前端跨域?

A JSONP
B script 標籤
C iframe 和 location.hash
D flash
E postMessage

答案: ABCDE
參考:http://www.cnblogs.com/rainma...
clipboard.png

看下列代碼,將會輸出什麼?(考查變量聲明提高)

var foo = 1;
function(){
    console.log(foo);
    var foo = 2;
    console.log(foo);
}

輸出undefined 和 2

如下代碼輸出什麼?(考查邏輯表達式)

console.log(1 && 2);

輸出: 2

如下代碼輸出什麼?(javascript)

console.log(1+"2"+"2"); 
console.log(1+ +"2"+"2");
console.log(1+ -"1"+2);
console.log(1+ -"1"+"2");
console.log(+"1"+2);
console.log(1+ "2");
console.log("A"-"B"+"2");
console.log("A"-"B"+2);

輸出: 122 32 2 02 3 12 NaN2 NaN

在body中插入「<ul><li>第一行...</li><li>...</li>...</ul>」,ul中有10個li,要求插入時考慮性能

頁面插入DOM會引發迴流和重繪。儘可能減小回流和重繪的次數爲主要思路。

參考: http://developer.51cto.com/ar...

談談cookies、sessionStorage、localStorage之間的區別?

主要從四個方面來回答:

  • 做用域
  • 大小
  • 生存週期
  • 存儲位置 sessionstorage和localstorage都是html5提供的客戶端存儲方式(都保存在客戶端)

區別:

  • cookie數據始終在同源的http請求中攜帶(即便不須要),即cookie在瀏覽器和服務器間來回傳遞;cookie數據還有路徑(path)的概念,能夠限制cookie只屬於某個路徑下。
  • 存儲大小限制也不一樣,cookie數據不能超過4k,同時由於每次http請求都會攜帶cookie,因此cookie只適合保存很小的數據,如會話標識。而sessionStorage和localStorage不會自動把數據發給服務器,僅在本地保存。sessionStorage和localStorage 雖然也有存儲大小的限制,但比cookie大得多,能夠達到5M或更大。
  • 數據有效期不一樣,sessionStorage:僅在當前瀏覽器窗口關閉前有效,天然也就不可能持久保持;localStorage:始終有效,窗口或瀏覽器關閉也一直保存,所以用做持久數據;cookie只在設置的cookie過時時間以前一直有效,即便窗口或瀏覽器關閉。
  • 做用域不一樣,sessionStorage不在不一樣的瀏覽器窗口中共享,即便是同一個頁面;localStorage 在全部同源窗口中都是共享的;cookie也是在全部同源窗口中都是共享的。Web Storage 支持事件通知機制,能夠將數據更新的通知發送給監聽者。Web Storage 的 api 接口使用更方便。

對象的深拷貝、淺拷貝?爲何須要深拷貝?

淺拷貝: 將原對象或原數組的引用直接賦給新對象,新數組,新對象/數組只是原對象的一個引用
深拷貝: 建立一個新的對象和數組,將原對象的各項屬性的「值」(數組的全部元素)拷貝過來,是「值」而不是「引用」

深拷貝對象(不討論數組的狀況):

  • 循環遍歷對象的屬性賦值
  • ES6的Object.assign: (用於對象的合併,將源對象(source)的全部可枚舉屬性,複製到目標對象(target),並返回合併後的target)
  • ES6擴展運算符:擴展運算符(...)用於取出參數對象的全部可遍歷屬性,拷貝到當前對象之中
  • JSON.parse(JSON.stringify(obj)): 上面三種方法不能拷貝全部層級,該方法能夠拷貝對象全部層級
  • 手動些遞歸(-_-!)

爲何須要深拷貝: 個人回答是 咱們拷貝的初衷是,建立一個新對象,該新對象擁有原有對象的全部屬性和方法。若是淺拷貝,那原對象改變,表面上看就是咱們拷貝的對象也變了。

數組去重方法有哪些?

方法:

  • 雙層循環去重(新數組保存,遍歷新數組查找有無已重複元素)
  • 排序後相鄰去除法
/*
* 給傳入數組排序,排序後相同值相鄰,
* 而後遍歷時,新數組只加入不與前一值重複的值。
* 會打亂原來數組的順序
* */
function uniq(array){
    array.sort();
    var temp=[array[0]];
    for(var i = 1; i < array.length; i++){
        if( array[i] !== temp[temp.length-1]){
            temp.push(array[i]);
        }
    }
    return temp;
}

var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));
  • 數組下標法
/*
*
* 仍是得調用「indexOf」性能跟方法1差很少,
* 實現思路:若是當前數組的第i項在當前數組中第一次出現的位置不是i,
* 那麼表示第i項是重複的,忽略掉。不然存入結果數組。
* */
function uniq(array){
    var temp = [];
    for(var i = 0; i < array.length; i++) {
        //若是當前數組的第i項在當前數組中第一次出現的位置是i,才存入數組;不然表明是重複的
        if(array.indexOf(array[i]) == i){
            temp.push(array[i])
        }
    }
    return temp;
}

var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));
  • 優化遍歷數組法
// 思路:獲取沒重複的最右一值放入新數組
    /*
    * 推薦的方法
    *
    * 方法的實現代碼至關酷炫,
    * 實現思路:獲取沒重複的最右一值放入新數組。
    * (檢測到有重複值時終止當前循環同時進入頂層循環的下一輪判斷)*/
    function uniq(array){
        var temp = [];
        var index = [];
        var l = array.length;
        for(var i = 0; i < l; i++) {
            for(var j = i + 1; j < l; j++){
                if (array[i] === array[j]){
                    i++;
                    j = i;
                }
            }
            temp.push(array[i]);
            index.push(i);
        }
        console.log(index);
        return temp;
    }
    
    var aa = [1,2,2,3,5,3,6,5];
    console.log(uniq(aa));
  • 對象鍵值法去重
/*
    * 速度最快, 佔空間最多(空間換時間)
    *
    * 該方法執行的速度比其餘任何方法都快, 就是佔用的內存大一些。
    * 現思路:新建一js對象以及新數組,遍歷傳入數組時,判斷值是否爲js對象的鍵,
    * 不是的話給對象新增該鍵並放入新數組。
    * 注意點:判斷是否爲js對象鍵時,會自動對傳入的鍵執行「toString()」,
    * 不一樣的鍵可能會被誤認爲同樣,例如n[val]-- n[1]、n["1"];
    * 解決上述問題仍是得調用「indexOf」。*/
    function uniq(array){
        var temp = {}, r = [], len = array.length, val, type;
        for (var i = 0; i < len; i++) {
            val = array[i];
            type = typeof val;
            if (!temp[val]) {
                temp[val] = [type];
                r.push(val);
            } else if (temp[val].indexOf(type) < 0) {
                temp[val].push(type);
                r.push(val);
            }
        }
        return r;
    }
    
    var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
    console.log(uniq(aa));
  • ES6
// ES6
function unique (arr) {
  const seen = new Map()
  return arr.filter((a) => !seen.has(a) && seen.set(a, 1))
}

談談react/vue/angular之間的差別、區別?

相關文章
相關標籤/搜索