BAT 前端開發面經 —— 吐血總結

更好閱讀,請移步這裏

聊以前

最近暑期實習招聘已經開始,我的目前參加了阿里的內推及騰訊和百度的實習生招聘,在此總結一下
一是備忘、總結提高,二是但願給你們一些參考
其餘面試及基礎相關能夠參考其餘博文:javascript

每位面試官的面試時間基本都在 40-80 分鐘,下面先簡要介紹各個面試流程,問題詳情見具體公司分類css

騰訊內推&校招 offer gothtml

首先騰訊分爲三面,都爲技術面:前端

  • 初試一個面試官
  • 複試兩個面試官,包括電話遠程 online codingvue

    (我也不知道爲何幾天內三個面試官面我,只算兩個面試過程 ヾ(´A`)ノ゚)
  • 終面一位面試官java

    這位應該是大 boss ,他說並非前端開發的,面試的問題也不會很深刻,主要看我的對這個領域的想法以及對常見問題在前端領域的解決思路,不按套路出牌,emmm 感受回答的不理想
    相似這種問題:
    • 說說最能體現你能力的工做
    • 網絡安全的實現node

      如何檢測惡意腳本
      如何屏蔽
      ...react

騰訊二面 & online codinggit

  • 騰訊的遠程 online coding 時間較長,大概一個多小時,不只要按要求編程,也要口述思路以及關鍵點,過程相似壓力面,面試官說完題目要求會給你思考及coding 時間,他能夠遠程看到面試者的 coding 狀態,主要考察應變能力,思惟活躍度,編碼習慣,調試能力,以及測試方法,本人在此過程當中沒有太注意測試過程,致使對於特殊狀況考慮不全面,測試樣例不完善,望小夥伴們注意 ヾ(´A`)ノ゚,不過,在口述代碼時發現也能夠本身提出來須要完善的地方。es6

  • coding 爲一到兩題,後續問題都是圍繞它結合實際應用進行拓展,主要考察是否能靈活運用以及類似的思路轉換,當時面試時間太長以及基礎知識較差,進制轉換,存儲那些個基礎被小學老師收回,一連串的炮轟簡直爽歪歪,我的表示此過程本身的表現較差,也要重視基礎基礎啊老鐵們 ( ̄_ ̄ )

經歷了騰訊雲的四個面試官,以及其餘部門一個面試官的醬油麪,騰訊的技術面試官廣泛語速較快,思路轉換很快,要跟上面試官的節奏,聊到本身比較熟悉的能夠多說幾句,他們也會順着你回答的內容進行深刻,也會引導面試者的回答方向,若是不太熟儘可能坦白一些,不懂裝懂很容易 gg

才接到通知另加兩輪面試委員會現場技術面,簡直爽歪歪 ヾ(´A`)ノ

騰訊校招現場

  • 一面

    面試官很 nice,基本看着簡歷問的,話題圍繞項目(項目隔得時間過久,心裏寧願粗暴的技術面),基本爲大體的瞭解,包括平時的學習習慣和關注的技術發展
    • 問到了 ES5 ES6 ES7 甚至 ES8
    • 項目中用過vue, 就問了 react vue 相關
    • 實習中的工做方式,如何處理設計師的設計稿,回答了包括考慮響應式佈局的經常使用方案
      • sass--定義function,使用rem

        問是否有其餘負面做用

        想到了頁面閃爍,因爲初始化時須要計算頁面尺寸,可能有縮放

        如何避免:

        <!-- 若是在頁面加載完成後,頁面是用js動態添加的,這個問題就不太明顯, -->
        doc.addEventListener('DOMContentLoaded‘', function(e) {
            <!-- doc.body.style.fontSize = 12 * dpr + 'px'; 淘寶處理 -->
        }, false);
      • 媒體查詢

    • 移動端和pc端的工做
  • 二面

    面試官不是前端的,因此沒有問很深刻的問題,主要模擬實際場景考察實現思路以及先後端的方案,後端沒說出什麼,基本上只是就前端層面進行了描述,包括實現思路、須要注意的問題、以及性能和安全方面的考慮
    • 前端安全
    • 場景考察
      • 直播彈幕處理
      • 後端返回大量數據且包含運算,如何實時顯示
      • 。。。記不清了
  • HR 面
    • 介紹經歷
    • 家庭狀況
    • 職業規劃
    • 對騰訊的認識及與其餘實習單位對比
    • 對比實習過的企業
    • 是否還報了其餘企業
    • 男友工做找的怎麼樣了

阿里內推 二面 卒

我投的是螞蟻金服的前端開發,投過簡歷硬生生排隊等了12天,還被內推人提早告知螞蟻的前端很嚴格 ( ̄_ ̄ )
阿里分爲在線測試,初試 ......

  • 首先是在線測試

    投完簡歷後官網會有相關在線測試題
    阿里前端的在線測試只有一道coding 題,限時 30 分,因爲初次在線答題,看着倒計時緊張的思路不通,未能準確理解題意,但實際題目並不難,考察使用原生 js 實現相似css 的層級選擇器的功能,具體題目記不太清,將僅存的記憶寫了下來並附上我的實現,詳情見本文後部分
  • 一面
  • 二面
  • 掛掉了。。。

baidu offer got

百度投的是核心搜索部門,但一面後估計不合適,沒有了消息,後簡歷轉到百度金融

  • 一面

    面試官語速很快,通常不給太多思考時間--------感受本身說話都打着節拍 ( ̄_ ̄ )

  • 二面

    面試官很和善,是惟一一個認真看了我博客的面試官,很榮幸,也很緊張

    基本偏向基礎
    但因爲沒安排好時間,面試時在戶外,聽不太清面試官的問題,在此提醒各位小夥伴提早選好面試場地,避免環境影響

  • 三面

    一樣和善的面試官,開始考察基礎知識,編譯原理,網絡協議等基礎,後面考察我的素質,後續更注重我的經歷,包括如何學習,找實習,實習中遇到的問題及如何解決,最驕傲的事情等等

關於結尾

  • 百度 & 阿里面試結束後都有問:你以爲在面試過程當中有什麼沒問到,但本身掌握比較好的技能麼

    面阿里時,頭腦發暈,回答:沒有,我感受您面的很專業,問的知識點都是比較核心的 ( ̄_ ̄ )
    百度經驗: 回答本身掌握還比較好的知識後,面試官真的會問不少問題(菜鳥能夠參考以上作法),若是面試官面試的較偏,倒能夠補充
  • 有什麼要問的
    • 騰訊二面教訓

      我:是否有導師帶,實習的大體安排以及部門業務等

      效果

      面試官曰:

      你那麼關係有沒有導師的問題,但學習中最重要的是靠本身,導師並非負責回答你全部問題的
    • 百度經驗

      我:部門是否有按期交流分享的機會;工做中是按照職位仍是業務部門劃分,如何交流;偏向頁面仍是業務邏輯

      我的在自學過程當中發現前端體系太大,不知對於前端學習,您有什麼建議麼

      面試官:不少前端初學者都有相似的困惑,你最好本身從頭開始作一個項目,無論是本身瞎想的仍是模仿的,在項目過程當中去發現須要學習什麼技術,在遇到問題的時候才知道去哪一個方向發展和思考,只有在項目中才能持續的學習和提升,前端知識很碎,沒有項目很難有一連串的經歷

整體

整體來講,面試中有按照面試題出的,也有直接聊的,通常也會結合實際工做中會遇到的場景以及技術中的一些坑,回答時結合本身的項目經驗會更好,大廠的面試官更側重於面試者對深層原理的理解,對於實習生來講通常面基礎,若是有深查原理的習慣,我的的可塑造性也會較高

三廠體驗對比:

  • 騰訊阿里面試官一面開始都比較側重實踐,若是簡歷上有過實踐項目和實習經歷,會問更實際的問題,構造場景讓解答
  • 協議都會問到

  • 相對來講,百度更多基礎知識點,更多考察對更基本的知識掌握,不限於前端,還包括組成原理和編譯原理的一些知識,固然前端偏多(好比選取一個class 標籤元素有幾種方式等小細節的問題來考察,細到要把每一個表達說完整,把每一個單詞拼出來)

  • 阿里騰訊更側重應用中的注意事項(如:IE 和其餘瀏覽器中的事件處理機制)不太揪細節

  • 三廠都有問到算法,騰訊相對更注重對算法和邏輯,對面試者基礎知識要求較高,甚至涉及更底層的。

  • 另兩廠對算法,數據結構的要求都是瞭解階段

如下爲面試中的一些知識點以及我的的一些補充,敲黑板啦啦啦

1. Tencent

1.1. js 的事件機制

事件階段

通常的,事件分爲三個階段:捕獲階段、目標階段和冒泡階段。

  • 捕獲階段(Capture Phase)

    • 事件的第一個階段是捕獲階段。事件從文檔的根節點流向目標對象節點。途中通過各個層次的DOM節點,並在各節點上觸發捕獲事件,直到到達事件的目標節點。捕獲階段的主要任務是創建傳播路徑,在冒泡階段,事件會經過這個路徑回溯到文檔跟節點。
    • 或這樣描述:

      任何事件產生時,如點擊一個按鈕,將從最頂端的容器開始(通常是html的根節點)。瀏覽器會向下遍歷DOM樹直到找到觸發事件的元素,一旦瀏覽器找到該元素,事件流就進入事件目標階段

  • 目標階段(Target Phase)

    • 當事件到達目標節點的,事件就進入了目標階段。事件在目標節點上被觸發,而後會逆向迴流,直到傳播至最外層的文檔節點。
  • 冒泡階段(Bubble Phase)
    • 事件在目標元素上觸發後,並不在這個元素上終止。它會隨着DOM樹一層層向上冒泡,回溯到根節點。
    • 冒泡過程很是有用。它將咱們從對特定元素的事件監聽中釋放出來,若是沒有事件冒泡,咱們須要監聽不少不一樣的元素來確保捕獲到想要的事件

事件處理程序

  • DOM0 級事件處理程序

    var btn5 = document.getElementById('btn5');
    btn5.onclick=function(){
       console.log(this.id);//btn5   
    };
    • 基於 DOM0 的事件,對於同一個 dom 節點而言,只能註冊一個,後邊註冊的 同種事件 會覆蓋以前註冊的。

      利用這個原理咱們能夠解除事件,btn5.onclick=null;其中this就是綁定事件的那個元素;
    • 以這種方式添加的事件處理程序會在事件流的冒泡階段被處理;

  • DOM2 級事件處理程序
    • DOM2支持同一dom元素註冊多個同種事件,事件發生的順序按照添加的順序依次觸發(IE是相反的)。
    • DOM2事件經過 addEventListenerremoveEventListener 管理

      // addEventListener(eventName,handlers,boolean);removeEventListener()
      // 兩個方法都同樣接收三個參數,第一個是要處理的事件名,第二個是事件處理程序,
      // 第三個值爲false時表示在事件冒泡階段調用事件處理程序,通常建議在冒泡階段使用,
      // 特殊狀況纔在捕獲階段;
      
      // 注意:經過addEventListener()添加的事件處理程序只能用removeEventListener()來移除
      // 而且移除時傳入的參數必須與添加時傳入的參數同樣;好比
      
      var btn2 = document.getElementById('btn2');
      var handlers = function () {
          console.log(this.id);
      };
      
      btn2.addEventListener('click',handlers,false);
      
      btn2.removeEventListener('click',handlers.false);
    • ie 事件處理程序

      //IE事件處理程序(IE和Opera支持)
      
      /* IE用了attachEvent(),detachEvent(),接收兩個參數,事件名稱和事件處理程序,
       * 經過attachEvent()添加的事件處理程序都會被添加到冒泡階段,因此平時爲了兼容更多的瀏覽器最好將事件添加到事件冒泡階段,IE8及之前只支持事件冒泡;
       */
      
      var btn3 = document.getElementById('btn3');
      var handlers2=function(){
          console.log(this===window); // true,注意attachEvent()添加的事件處理程序運行在全局做用域;
      };
      
      btn3.attachEvent('onclick',handlers2);
---ie 與其餘瀏覽器的區別

總結

DOM事件模型中的事件對象經常使用屬性:

  • type用於獲取事件類型
  • target獲取事件目標
  • stopPropagation()阻止事件冒泡
  • preventDefault()阻止事件默認行爲
  • 判斷加載狀態 —— onload 事件

IE事件模型中的事件對象經常使用屬性:

  • type用於獲取事件類型
  • srcElement獲取事件目標
  • cancelBubble 阻止事件冒泡
  • returnValue 阻止事件默認行爲
  • 經過 readystate 屬性值判斷什麼時候方法下載完畢可用

    readystate共有如下幾個值:
    • uninitialized: 對象存在但未初始化;
    • loading:對象正在加載;
    • loaded:對象數據加載完畢;
    • interactive:能夠操做對象了,但還沒加載完畢;
    • complete:加載完畢。

    注意上面5個值並不必定每一個事件都全包含,而且不必定是什麼順序。

    Document.readyState 屬性
    一個文檔的 readyState 能夠是如下之一:
    • loading / 加載

      document 仍在加載。
    • interactive / 互動

      文檔已經完成加載,文檔已被解析,可是諸如圖像,樣式表和框架之類的子資源仍在加載。
    • complete / 完成

      T文檔和全部子資源已完成加載。狀態表示 load 事件即將被觸發。

    當這個屬性的值變化時,document 對象上的readystatechange 事件將被觸發。

事件對象

  • IE

    IE中事件對象是做爲全局對象 window.event 存在的
  • Firefox

    Firefox中則是作爲句柄( handler )的第一個參數傳入
  • 通用

    var evt = window.event || arguments[0];

事件監聽

  • Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
    js addEventListener(eventName,handler,boolean); removeEventListener() /* 兩個方法都同樣接收三個參數, * 事件名 * 事件處理程序 * boolean false時表示在事件冒泡階段調用事件處理程序,通常建議在冒泡階段使用 */

  • IE8.0及其如下版本
    js element.attachEvent(type, handler); element.detachEvent(type, handler); /* element 要綁定事件的對象,html 節點 * type 事件類型 +'on' 如: "onclick, onmouseover" * listener 事件處理程序(只寫函數名,不帶括號) */

  • 早期瀏覽器
    obj['on' + type] = handler

阻止冒泡

  • event.stopPropagation
  • event.cancelBubble = true //IE

阻止默認事件

  • event.preventDefault()
  • event.returnValue = false //IE
---通用的事件監聽器
// event(事件)工具集,來源:github.com/markyun
markyun.Event = {
    // 頁面加載完成後
    readyEvent: function (fn) {
        if (fn == null) {
            fn = document;
        }
        var oldonload = window.onload;
        if (typeof window.onload != 'function') {
            window.onload = fn;
        } else {
            window.onload = function () {
                oldonload();
                fn();
            };
        }
    },
    // 視能力分別使用dom0||dom2||IE方式 來綁定事件
    // 參數: 操做的元素,事件名稱 ,事件處理程序
    addEvent: function (element, type, handler) {
        if (element.addEventListener) {
            //事件類型、須要執行的函數、是否捕捉
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent) {
            element.attachEvent('on' + type, function () {
                handler.call(element);
            });
        } else {
            element['on' + type] = handler;
        }
    },
    // 移除事件
    removeEvent: function (element, type, handler) {
        if (element.removeEnentListener) {
            element.removeEnentListener(type, handler, false);
        } else if (element.detachEvent) {
            element.detachEvent('on' + type, handler);
        } else {
            element['on' + type] = null;
        }
    },
    // 阻止事件 (主要是事件冒泡,由於IE不支持事件捕獲)
    stopPropagation: function (ev) {
        if (ev.stopPropagation) {
            ev.stopPropagation();
        } else {
            ev.cancelBubble = true;
        }
    },
    // 取消事件的默認行爲
    preventDefault: function (event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },
    // 獲取事件目標
    getTarget: function (event) {
        return event.target || event.srcElement;
    },
    // 獲取event對象的引用,取到事件的全部信息,確保隨時能使用event;
    getEvent: function (e) {
        var ev = e || window.event;
        if (!ev) {
            var c = this.getEvent.caller;
            while (c) {
                ev = c.arguments[0];
                if (ev && Event == ev.constructor) {
                    break;
                }
                c = c.caller;
            }
        }
        return ev;
    }
};

1.2. vue

---Vue 生命週期
---雙向綁定原理 & 如何實現
---vuex 原理
---vue 數據更新後執行

1.3. 跨域

什麼叫跨域

方案

1.4. 安全 && 怎樣預防

1.6. 本地存儲

1.7. 瀏覽器緩存

1.8. 頁面從輸入URL 到加載過程

1.9. HTTP

---content-type
  • application/x-www-form-urlencoded

    最多見的 POST 提交數據的方式了。瀏覽器的原生 form 表單,若是不設置 enctype 屬性,那麼最終就會以 application/x-www-form-urlencoded方式提交數據。

    傳遞的key/val會通過URL轉碼,因此若是傳遞的參數存在中文或者特殊字符須要注意。

    //例子
    //b=曹,a=1
    
    POST  HTTP/1.1(CRLF)
    Host: www.example.com(CRLF)
    Content-Type: application/x-www-form-urlencoded(CRLF)
    Cache-Control: no-cache(CRLF)
    (CRLF)
    b=%E6%9B%B9&a=1(CRLF)
    //這裏b參數的值"曹"由於URL轉碼變成其餘的字符串了
  • multipart/form-data

    常見的 POST 數據提交的方式。咱們使用表單上傳文件時,必須讓 form 的 enctyped 等於這個值
    而且Http協議會使用boundary來分割上傳的參數

  • text/xml

    <!-- 例子 -->
    POST http://www.example.com HTTP/1.1(CRLF) 
    Content-Type: text/xml(CRLF)
    (CRLF)
    <?xml version="1.0"?>
    <resource>
        <id>123</id>
        <params>
            <name>
                <value>homeway</value>
            </name>
            <age>
                <value>22</value>
            </age>
        </params>
    </resource>
  • application/json

    用來告訴服務端消息主體是序列化後的 JSON 字符串

    //例子
    //傳遞json
    
    POST  HTTP/1.1(CRLF)
    Host: www.example.com(CRLF)
    Content-Type: application/json(CRLF)
    Cache-Control: no-cache(CRLF)
    Content-Length: 24(CRLF)
    (CRLF)
    {
        "a":1,
        "b":"hello"
    }

(CRLF)指 \r\n
參考: HTTP常見Content-Type比較

1.10. get & post

1.11. TCP & UDP & 握手

---TCP (Transmission Control Protocol)

兩個序號和三個標誌位:

  • 序號:seq序號,佔32位,用來標識從TCP源端向目的端發送的字節流,發起方發送數據時對此進行標記。
  • 確認序號:ack序號,佔32位,只有ACK標誌位爲1時,確認序號字段纔有效,ack=seq+1。

標誌位:共6個,即URG、ACK、PSH、RST、SYN、FIN等,具體含義以下:

  • URG:緊急指針(urgent poin* 有效。
  • ACK:acknowledgement 確認序號有效。
  • PSH:接收方應該儘快將這個報文交給應用層。
  • RST:reset 重置鏈接。
  • SYN:synchronous 創建聯機,發起一個新鏈接。
  • FIN:finish 釋放一個鏈接。

須要注意的是:

  • 不要將確認序號ack與標誌位中的ACK搞混了。
  • 確認方ack=發起方req+1,兩端配對。

  1. 第一次握手:
    Client將標誌位SYN置爲1,隨機產生一個值 seq=J,並將該數據包發送給Server
    Client進入SYN_SENT狀態,等待Server確認。
  2. 第二次握手:
    Server收到數據包後由標誌位SYN=1知道Client請求創建鏈接,Server將標誌位SYN和ACK都置爲1,ack=J+1,隨機產生一個值seq=K,並將該數據包發送給Client以確認鏈接請求,Server進入SYN_RCVD狀態。
  3. 第三次握手:
    Client收到確認後,檢查ack是否爲J+1,ACK是否爲1,若是正確則將標誌位ACK置爲1,ack=K+1,並將該數據包發送給Server,Server檢查ack是否爲K+1,ACK是否爲1,若是正確則鏈接創建成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client與Server之間能夠開始傳輸數據了

爲何須要確認

---四次揮手

因爲TCP鏈接時全雙工的,所以,每一個方向都必需要單獨進行關閉,這一原則是當一方完成數據發送任務後,發送一個FIN來終止這一方向的鏈接,收到一個FIN只是意味着這一方向上沒有數據流動了,即不會再收到數據了,可是在這個TCP鏈接上仍然可以發送數據,直到這一方向也發送了FIN

首先進行關閉的一方將執行主動關閉,而另外一方則執行被動關閉,上圖描述的便是如此。

  • 第一次揮手:
    Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。
  • 第二次揮手:
    Server收到FIN後,發送一個ACK給Client,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號),Server進入CLOSE_WAIT狀態。
  • 第三次揮手:
    Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態。
  • 第四次揮手:
    Client收到FIN後,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號爲收到序號+1,Server進入CLOSED狀態,完成四次揮手。

爲何TIME_WAIT狀態須要通過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

  • 可靠的實現 TCP 全雙工鏈接的終止
  • 容許老的重複分節在網絡中消失

MSL是Maximum Segment Lifetime英文的縮寫,中文能夠譯爲「報文最大生存時間」,他是任何報文在網絡上存在的最長時間,超過這個時間報文將被丟棄,RFC 793中規定MSL爲2分鐘,實際應用中經常使用的是30秒,1分鐘和2分鐘等。2MSL即兩倍的MSL,TCP的TIME_WAIT狀態也稱爲2MSL等待狀態

爲何鏈接的時候是三次握手,關閉的時候倒是四次握手?

  • 由於當Server端收到Client端的SYN鏈接請求報文後,能夠直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。可是關閉鏈接時
  • 當Server端收到FIN報文時,極可能並不會當即關閉SOCKET,因此只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端全部的報文都發送完了,我才能發送FIN報文,所以不能一塊兒發送。故須要四步握手。

參考: TCP三次握手詳解及釋放鏈接過程

1.12. HTTP 加密

---加密對象

對於HTTP協議來講,加密的對象有如下兩個:

  • 對通訊的加密:
    HTTP中沒有加密功能,可是能夠經過和SSL(Secure Socket Layer,安全套接層)組合使用,加密通訊內容。使用SSL創建安全通訊線路後,就能夠在這條線路上進行HTTP通訊了。與SSL組合使用的HTTP被稱爲HTTPS(HTTP Secure,超文本傳輸安全協議)。
  • 對通訊內容自己進行加密
    即對HTTP報文裏所包含的內容進行加密。這樣,首先客戶端要先對報文進行加密,而後再發給服務器。服務器在接受到請求時,須要對報文進行解密,再處理報文。該方式不一樣於SSL將整個通訊線路進行加密處理,因此內容仍然有被篡改的風險。
    • A、任何人均可以發起請求
      HTTP協議中,並未有確認通訊方這一步驟,因此,任何人均可以發送請求,而服務器在接受到任何請求時,都會作出相應的響應。
      • 解決方案:

        查明對手的證書

        雖然HTTP不能確認通訊方,但SSL是能夠的。SSL不只提供了加密處理,還使用了"證書"的手段,可用於確認通訊方。證書是由值得信賴的第三方機構頒佈,可用於肯定證實服務器和客戶端是實際存在的。因此,只要能確認通訊方持有的證書,便可判斷通訊方的真實意圖。
    • B、沒法判斷報文是否完整(報文可能已遭篡改)

      HTTP協議沒法判斷報文是否被篡改,在請求或者響應發出後,在對方接收以前,即便請求或者響應遭到篡改是沒法得知的。
      • 防止篡改:

        經常使用的,肯定報文完整性方法:MD五、SHA-1 等 散列值校驗方法,以及用來確認文件的數字簽名方法。可是,使用這些方法,也沒法百分百確保結果正確,由於MD5自己被修改的話,用戶是沒辦法意識到得。

    爲了有效防止這些弊端,能夠採用HTTPS。
  • POST 用戶安全登錄

    在關係到用戶隱私的時候,要時刻遵循兩個原則:
    • 任何應用程序都不能在本地存儲與安全相關的用戶信息
    • 任何應用程序在向服務器傳遞數據的時候,都不能直接傳遞與安全相關的用戶信息。

    要想讓用戶信息安全,就必須對其進行加密,讓別人即使是拿到了安全信息,擺在眼前的也是一串亂碼,沒有半點用處

    MD5是一種經常使用的加密方法,它是一種散列函數,利用MD5對用戶信息進行加密,會增長用戶信息安全性。

    網上有關於MD5的第三方框架Category

    利用這個第三方框架能夠實現對密碼進行MD5加密

    +隨機亂碼字符防止被破解

---加密算法

對稱加密

非對稱加密

---HTTPS 加密原理

HTTPS簡介

HTTPS實際上是有兩部分組成:HTTP + SSL / TLS,也就是在HTTP上又加了一層處理加密信息的模塊。服務端和客戶端的信息傳輸都會經過TLS進行加密,因此傳輸的數據都是加密後的數據

SSL協議是經過非對稱密鑰機制保證雙方身份認證,並完成創建鏈接,在實際數據通訊時經過對稱密鑰機制保障數據安全性

  • 服務器 用RSA生成公鑰和私鑰

  • 把公鑰放在證書裏發送給客戶端,私鑰本身保存

  • 客戶端首先向一個權威的服務器檢查證書的合法性,若是證書合法,客戶端產生一段隨機數,這個隨機數就做爲通訊的密鑰,咱們稱之爲對稱密鑰,用公鑰加密這段隨機數,而後發送到服務器

  • 服務器用密鑰解密獲取對稱密鑰,而後,雙方就已對稱密鑰進行加密解密通訊了

HTTPS 在傳輸數據以前須要客戶端(瀏覽器)與服務端(網站)之間進行一次握手,在握手過程當中將確立雙方加密傳輸數據的密碼信息。TLS/SSL 協議不只僅是一套加密傳輸的協議,更是一件通過藝術家精心設計的藝術品,TLS/SSL 中使用了非對稱加密,對稱加密以及 HASH 算法。握手過程的具體描述以下:

  1. 瀏覽器將本身支持的一套加密規則發送給網站。
  2. 網站從中選出一組加密算法與HASH算法,並將本身的身份信息以證書的形式發回給瀏覽器。證書裏面包含了網站地址,加密公鑰,以及證書的頒發機構等信息。
  3. 瀏覽器得到網站證書以後瀏覽器要作如下工做:

    a) 驗證證書的合法性(頒發證書的機構是否合法,證書中包含的網站地址是否與正在訪問的地址一致等),若是證書受信任,則瀏覽器欄裏面會顯示一個小鎖頭,不然會給出證書不受信的提示。

    b) 若是證書受信任,或者是用戶接受了不受信的證書,瀏覽器會生成一串隨機數的密碼,並用證書中提供的公鑰加密。

    c) 使用約定好的HASH算法計算握手消息,並使用生成的隨機數對消息進行加密,最後將以前生成的全部信息發送給網站。
  4. 網站接收瀏覽器發來的數據以後要作如下的操做:

    a) 使用本身的私鑰將信息解密取出密碼,使用密碼解密瀏覽器發來的握手消息,並驗證HASH是否與瀏覽器發來的一致。

    b) 使用密碼加密一段握手消息,發送給瀏覽器。
  5. 瀏覽器解密並計算握手消息的HASH,若是與服務端發來的HASH一致,此時握手過程結束,以後全部的通訊數據將由以前瀏覽器生成的隨機密碼並利用對稱加密算法進行加密。

參考:圖解HTTPS

如何保證 HTTP 傳輸安全性

  • 重要的數據,要加密

    好比用戶名密碼(若是簡單的md5,是能夠暴力破解),常見的是 md5(不可逆),aes(可逆),自由組合,還能夠加一些特殊字符

    舉例:username = aes(username), pwd = MD5(pwd + username)

  • 非重要數據,要簽名

    簽名的目的是爲了防止篡改,好比 http://www.xxx.com/getnews?id=1,獲取id爲1的新聞,若是不簽名那麼經過id=2,就能夠獲取2的內容等等。怎樣簽名呢?

    一般使用sign,好比原連接請求的時候加一個 sign 參數,sign=md5(id=1),服務器接受到請求,驗證sign是否等於 md5(id=1) ,若是等於說明正常請求。

    這會有個弊端,假如規則被發現,那麼就會被僞造,因此適當複雜一些,仍是可以提升安全性的。

  • 登陸態怎麼作

    http是無狀態的,也就是服務器無法本身判斷兩個請求是否有聯繫,那麼登陸以後,之後的接口怎麼斷定是否登陸呢

    簡單的作法,在數據庫中存一個token字段(名字隨意),當用戶調用登錄接口成功的時候,就將該字段設一個值,(好比aes(過時時間)),同時返回給前端,之後每次前端請求帶上該值,服務器首先校驗是否過時,其次校驗是否正確,不經過就讓其登錄。(redis 作這個很方便哦,key有過時時間)

來自:如何保證http傳輸安全性

1.13. 排序:冒泡,選擇,快速

1.14. 數據庫

---觸發器

一種特殊的存儲過程,存儲過程通常經過定義的名字直接調用,而觸發器是經過增、刪、改進行觸發執行的。會在事件發生時自動強制執行

觸發器是一種特殊的存儲過程,主要是經過事件來觸發而被執行的。它能夠強化約束,來維護數據的完整性和一致性,能夠跟蹤數據庫內的操做從而不容許未經許可的更新和變化。能夠聯級運算。如,某表上的觸發器上包含對另外一個表的數據操做,而該操做又會致使該表觸發器被觸發。

---事務 & 鎖
  • 事務

    就是被綁定在一塊兒做爲一個邏輯工做單元的SQL語句分組,若是任何一個語句操做失敗那麼整個操做就被失敗,之後操做就會回滾到操做前狀態,或者是上有個節點。

    爲了確保要麼執行,要麼不執行,就能夠使用事務。要將一組語句做爲事務考慮,就須要經過ACID測試,即原子性,一致性,隔離性和持久性。
  • 鎖:

    在全部的DBMS中,鎖是實現事務的關鍵,鎖能夠保證事務的完整性和併發性。與現實生活中鎖同樣,它能夠使某些數據的擁有者,在某段時間內不能使用某些數據或數據結構。固然鎖還分級別的。共享鎖(只讀不寫)、排他鎖(可讀可寫)

1.15. 軟件設計模式

設計原則

  • 對接口編程而不是對實現編程
  • 優先使用對象組合而不是繼承

---單例模式

單體是一個用來劃分命名空間並將一批相關的屬性和方法組織在一塊兒的對象,若是他能夠被實例化,那麼他只能被實例化一次

// 對象字面量
var Singleton = {
    attr1: 1,
    attr2: 2,
    method1: function(){
        return this.attr1;
    },
    method2: function(){
        return this.attr2;
    }
};

// 上面的全部成員變量都是經過Singleton來訪問的,可是它並非單體模式;

// 由於單體模式還有一個更重要的特色,就是能夠僅被實例化一次,上面的只是不能被實例化的一個類,所以不是單體模式;對象字面量是用來建立單體模式的方法之一;


/*要實現一個單體模式的話,咱們無非就是使用一個變量來標識該類是否被實例化
若是未被實例化的話,那麼咱們能夠實例化一次,不然的話,直接返回已經被實例化的對象
*/

// 單體模式
var Singleton = function(name){
    this.name = name;
    this.instance = null;
};
Singleton.prototype.getName = function(){
    return this.name;
}
// 獲取實例對象
function getInstance(name) {
    if(!this.instance) {
        this.instance = new Singleton(name);
    }
    return this.instance;
}
// 測試單體模式的實例
var a = getInstance("aa");  
var b = getInstance("bb");

console.log(a === b)        // true
console.log(a.getName())    // aa
console.log(b.getName())    // aa

應用案例

  • 彈窗

    傳統建立:好比我點擊一個元素須要建立一個div,我點擊第二個元素又會建立一次div,咱們頻繁的點擊某某元素,他們會頻繁的建立div的元素,雖然當咱們點擊關閉的時候能夠移除彈出代碼,可是呢咱們頻繁的建立和刪除並很差,特別對於性能會有很大的影響,對DOM頻繁的操做會引發重繪等,從而影響性能;所以這是很是很差的習慣;咱們如今能夠使用單體模式來實現彈窗效果,咱們只實例化一次就能夠

編寫通用的單體模式

咱們使用一個參數fn傳遞進去,若是有result這個實例的話,直接返回,不然的話,當前的getInstance函數調用fn這個函數,是this指針指向與這個fn這個函數;以後返回被保存在result裏面;如今咱們能夠傳遞一個函數進去,無論他是建立div也好,仍是建立iframe也好,總之若是是這種的話,均可以使用getInstance來獲取他們的實例對象;

// 建立div
var createWindow = function(){
    var div = document.createElement("div");
    div.innerHTML = "我是彈窗內容";
    div.style.display = 'none';
    document.body.appendChild(div);
    return div;
};
// 建立iframe
var createIframe = function(){
    var iframe = document.createElement("iframe");
    document.body.appendChild(iframe);
    return iframe;
};
// 獲取實例的封裝代碼
var getInstance = function(fn) {
    var result;
    return function(){
        return result || (result = fn.call(this,arguments));
    }
};
// 測試建立div
var createSingleDiv = getInstance(createWindow);
document.getElementById("Id").onclick = function(){
    var win = createSingleDiv();
    win.style.display = "block";
};
// 測試建立iframe
var createSingleIframe = getInstance(createIframe);
document.getElementById("Id").onclick = function(){
    var win = createSingleIframe();
    win.src = "http://cnblogs.com";
};
---如下爲補充
---工廠模式

客戶類和工廠類分開。消費者任什麼時候候須要某種產品,只需向工廠請求便可。消費者無須修改就能夠接納新產品。

工廠模式是爲了解決多個相似對象聲明的問題;也就是爲了解決實列化對象產生重複的問題。

  • 優勢:能解決多個類似的問題。
  • 缺點:
    • 不能知道對象識別的問題(對象的類型不知道)。
    • 當產品修改時,工廠類也要作相應的修改。
function CreatePerson(name,age,sex) {
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.sex = sex;
    obj.sayName = function(){
        return this.name;
    }
    return obj;
}
var p1 = new CreatePerson("longen",'28','男');
var p2 = new CreatePerson("tugenhua",'27','女');
---模塊模式

模塊模式的思路是爲單體模式添加私有變量和私有方法可以減小全局變量的使用

prototype + constructor

---裝飾者模式

裝飾者(decorator)模式可以在不改變對象自身的基礎上,在程序運行期間給對像動態的添加職責(方法或屬性)。
與繼承相比,裝飾者是一種更輕便靈活的作法。

能夠動態的給某個對象添加額外的職責,而不會影響從這個類中派生的其它對象。

// ES7裝飾器
function isAnimal(target) {
    target.isAnimal = true
    return target
}

// 裝飾器
@isAnimal
class Cat {
    // ...
}
console.log(Cat.isAnimal)    // true

// 做用於類屬性的裝飾器:
function readonly(target, name, descriptor) {
    discriptor.writable = false
    return discriptor
}
class Cat {
    @readonly
    say() {
        console.log("meow ~")
    }
}

var kitty = new Cat()
kitty.say = function() {
    console.log("woof !")
}
kitty.say()    // meow ~
---觀察者模式(發佈-訂閱)

發佈---訂閱模式又叫觀察者模式,它定義了對象間的一種一對多的關係,讓多個觀察者對象同時監聽某一個主題對象,當一個對象發生改變時,全部依賴於它的對象都將獲得通知

發佈訂閱模式的流程以下:

  1. 肯定誰是發佈者(好比個人博客)。
  2. 而後給發佈者添加一個緩存列表,用於存放回調函數來通知訂閱者。
  3. 發佈消息,發佈者須要遍歷這個緩存列表,依次觸發裏面存放的訂閱者回調函數。
  4. 退訂(好比不想再接收到這些訂閱的信息了,就能夠取消掉)

【實現事件模型】

即寫一個類或是一個模塊,有兩個函數,一個bind一個trigger,分別實現綁定事件和觸發事件,核心需求就是能夠對某一個事件名稱綁定多個事件響應函數,而後觸發這個事件名稱時,依次按綁定順序觸發相應的響應函數。

大體實現思路就是建立一個類或是匿名函數,在bind和trigger函數外層做用域建立一個字典對象,用於存儲註冊的事件及響應函數列表,bind時,若是字典沒有則建立一個,key是事件名稱,value是數組,裏面放着當前註冊的響應函數,若是字段中有,那麼就直接push到數組便可。trigger時調出來依次觸發事件響應函數便可

var Event = (function(){
    var list = {},
        listen,
        trigger,
        remove;
        listen = function(key,fn){
            if(!list[key]) {
                list[key] = [];
            }
            list[key].push(fn);
        };
        trigger = function(){
            var key = Array.prototype.shift.call(arguments),
                fns = list[key];
            if(!fns || fns.length === 0) {
                return false;
            }
            for(var i = 0, fn; fn = fns[i++];) {
                fn.apply(this,arguments);
            }
        };
        remove = function(key,fn){
            var fns = list[key];
            if(!fns) {
                return false;
            }
            if(!fn) {
                fns && (fns.length = 0);
            }else {
                for(var i = fns.length - 1; i >= 0; i--){
                    var _fn = fns[i];
                    if(_fn === fn) {
                        fns.splice(i,1);
                    }
                }
            }
        };
        return {
            listen: listen,
            trigger: trigger,
            remove: remove
        }
})();

// 測試代碼以下:
Event.listen("color",function(size) {
    console.log("尺碼爲:"+size); // 打印出尺碼爲42
});
Event.trigger("color",42);
---代理模式

代理是一個對象,它能夠用來控制對本體對象的訪問,它與本體對象實現了一樣的接口,代理對象會把全部的調用方法傳遞給本體對象的
本地對象注重的去執行頁面上的代碼,代理則控制本地對象什麼時候被實例化,什麼時候被使用

優勢:

  • 代理對象能夠代替本體被實例化,並使其能夠被遠程訪問;
  • 它還能夠把本體實例化推遲到真正須要的時候;對於實例化比較費時的本體對象,或者由於尺寸比較大以致於不用時不適於保存在內存中的本體,咱們能夠推遲實例化該對象;
// 先申明一個奶茶妹對象
var TeaAndMilkGirl = function(name) {
    this.name = name;
};
// 這是京東ceo先生
var Ceo = function(girl) {
    this.girl = girl;
    // 送結婚禮物 給奶茶妹
    this.sendMarriageRing = function(ring) {
        console.log("Hi " + this.girl.name + ", ceo送你一個禮物:" + ring);
    }
};
// 京東ceo的經紀人是代理,來代替送
var ProxyObj = function(girl){
    this.girl = girl;
    // 經紀人代理送禮物給奶茶妹
    this.sendGift = function(gift) {
        // 代理模式負責本體對象實例化
        (new Ceo(this.girl)).sendMarriageRing(gift);
    }
};
// 初始化
var proxy = new ProxyObj(new TeaAndMilkGirl("奶茶妹"));
proxy.sendGift("結婚戒"); // Hi 奶茶妹, ceo送你一個禮物:結婚戒
  • TeaAndMilkGirl 是一個被送的對象(這裏是奶茶妹);
  • Ceo 是送禮物的對象,他保存了奶茶妹這個屬性,及有一個本身的特權方法sendMarriageRing 就是送禮物給奶茶妹這麼一個方法;
  • 而後呢他是想經過他的經紀人去把這件事完成,因而須要建立一個經濟人的代理模式,名字叫ProxyObj ;
  • 他的主要作的事情是,把ceo交給他的禮物送給ceo的情人,所以該對象一樣須要保存ceo情人的對象做爲本身的屬性,同時也須要一個特權方法sendGift ,該方法是送禮物,所以在該方法內能夠實例化本體對象,這裏的本體對象是ceo送花這件事情,所以須要實例化該本體對象後及調用本體對象的方法(sendMarriageRing).

理解使用虛擬代理實現圖片的預加載

在網頁開發中,圖片的預加載是一種比較經常使用的技術,若是直接給img標籤節點設置src屬性的話,若是圖片比較大的話,或者網速相對比較慢的話,那麼在圖片未加載完以前,圖片會有一段時間是空白的場景,這樣對於用戶體驗來說並很差,那麼這個時候咱們能夠在圖片未加載完以前咱們能夠使用一個loading加載圖片來做爲一個佔位符,來提示用戶該圖片正在加載,等圖片加載完後咱們能夠對該圖片直接進行賦值便可;下面咱們先不用代理模式來實現圖片的預加載的狀況下代碼以下:

// 不使用代理的預加載圖片函數以下
var myImage = (function(){
    var imgNode = document.createElement("img");
    document.body.appendChild(imgNode);
    var img = new Image();
    img.onload = function(){
        imgNode.src = this.src;
    };
    return {
        setSrc: function(src) {
            imgNode.src = "http://img.lanrentuku.com/img/allimg/1212/5-121204193Q9-50.gif";
            img.src = src;
        }
    }
})();
// 調用方式
myImage.setSrc("https://img.alicdn.com/tps/i4/TB1b_neLXXXXXcoXFXXc8PZ9XXX-130-200.png");
//利用代理模式來編寫預加載圖片
var myImage = (function(){
    var imgNode = document.createElement("img");
    document.body.appendChild(imgNode);
    return {
        setSrc: function(src) {
            imgNode.src = src;
        }
    }
})();

// 代理模式
var ProxyImage = (function(){
    var img = new Image();
    img.onload = function(){
        myImage.setSrc(this.src);
    };
    return {
        setSrc: function(src) {
                    myImage.setSrc("http://img.lanrentuku.com/img/allimg/1212/5-121204193Q9-50.gif");
                    img.src = src;
        }
    }
})();
// 調用方式
ProxyImage.setSrc("https://img.alicdn.com/tps/i4/TB1b_neLXXXXXcoXFXXc8PZ9XXX-130-200.png");

這種懶加載方法不用代理模式也是能夠實現的,只是用代理模式。咱們可讓 myImage 只作一件事,只負責將實際圖片加入到頁面中,而loading圖片交給ProxyImage去作。從而下降代碼的耦合度。由於當我不想用loading的時候,能夠直接調用myImage 方法。也便是說假如我門不須要代理對象的話,直接能夠換成本體對象調用該方法便可
對比

  • 不代理:不知足單一職責原則,代碼耦合度高
  • myimage 函數只負責一件事,其餘交給代理

優勢

  • 用戶能夠放心地請求代理,他們只關心是否能獲得想要的結果。假如我門不須要代理對象的話,直接能夠換成本體對象調用該方法便可。
  • 在任何使用本體對象的地方均可以替換成使用代理。

參考:Javascript設計模式詳解

1.2. Online Coding

js 實現兩個超大數相加
基礎:

  • JS 中全部的數字類型,實際存儲都是經過 8 字節 double 浮點型 表示的,並非可以精確表示範圍內的全部數
  • 大整數存儲(安全使用範圍)
    • 其餘語言 2^63 - 1
    • js Math.pow(2, 53) - 1
      js //js 最大和最小安全值 Number.MAX_SAFE_INTEGER //9007199254740991 Number.MIN_SAFE_INTEGER //-9007199254740991
var largeNumberAdd = function(num1, num2) {
    var arr1 = num1.split(''),
        arr2 = num2.split(''),
        tem = '',
        num3 = 0,
        result = []
    var longDiff = arr1.length - arr2.length
    if (longDiff > 0) {
        for (let i = 0; i < longDiff; i++) {
            arr2.unshift('0')            
        }
    }else if (longDiff < 0) {
        for (let i = 0; i < Math.abs(longDiff); i++) {
            arr1.unshift('0')
        }
    }
    for (let i = arr1.length - 1; i >= 0; i--) {
        tem = parseInt(arr1[i]) + parseInt(arr2[i]) + num3
        // check if tem > 10
        if (tem >= 10) {
            num3 = 1
            result.push((tem + '')[1])
        }else {
            num3 = 0
            result.push(tem)
        }
    }
    return result.reverse().join('')
}

// console.log(largeNumberAdd('11111','11111'))
console.log(largeNumberAdd('00000000000000000000011111','333331999'))
console.log(11111+333331999)
// console.log(largeNumberAdd('3333333333333333333333333333333311111111111111111111111111111111111111','333333333333333331111111111111111111111111111166666666666666'))

js 每秒鐘的計算量
js 如何解析後臺返回的超大數據
前提:

  • js 用浮點數表示全部64位數字,全部達到 2^53 的能夠被精確表示,更大的數字都會被裁剪,——如何表示64位數字
    雖然js 可以解析進制數字表示64位數字,但底層的數字表示不支持 64 位
    在瀏覽器中執行如下代碼

    <html>
    <head>
        <script language="javascript">
        function showPrecisionLimits() {
            document.getElementById("r50").innerHTML = 0x0004000000000001 - 0x0004000000000000;
            document.getElementById("r51").innerHTML = 0x0008000000000001 - 0x0008000000000000;
            document.getElementById("r52").innerHTML = 0x0010000000000001 - 0x0010000000000000;
            document.getElementById("r53").innerHTML = 0x0020000000000001 - 0x0020000000000000;
            document.getElementById("r54").innerHTML = 0x0040000000000001 - 0x0040000000000000;
        }
        </script>
    </head>
    <body onload="showPrecisionLimits()">
        <p>(2^50+1) - (2^50) = <span id="r50"></span></p>
        <p>(2^51+1) - (2^51) = <span id="r51"></span></p>
        <p>(2^52+1) - (2^52) = <span id="r52"></span></p>
        <p>(2^53+1) - (2^53) = <span id="r53"></span></p>
        <p>(2^54+1) - (2^54) = <span id="r54"></span></p>
    </body>
    </html>

    在Firefox,Chrome和IE瀏覽器中,能夠看到,若是可以存儲64位數字,則如下減法結果皆爲1。而結果相反,能夠看到2 ^ 53 + 1和2 ^ 53 間的差別丟失
    js (2 ^ 50 + 1) - (2 ^ 50)= 1 (2 ^ 51 + 1) - (2 ^ 51)= 1 (2 ^ 52 + 1) - (2 ^ 52)= 1 (2 ^ 53 + 1) - (2 ^ 53)= 0 (2 ^ 54 + 1) - (2 ^ 54)= 0

    位運算
    所以,咱們能夠選擇用兩個 32 位的數字表示 64 位整數,而後進行按位與

    var a = [ 0x0000ffff, 0xffff0000 ];
    var b = [ 0x00ffff00, 0x00ffff00 ];
    var c = [ a[0] & b[0], a[1] & b[1] ];
    
    document.body.innerHTML = c[0].toString(16) + ":" + c[1].toString(16);
    
    //結果
    ff00:ff0000

網絡安全

前端網絡安全的實現

  • 保證http傳輸安全性

如何檢測惡意腳本
如何屏蔽

2. 阿里

一面

  1. 簡單介紹一下本身
  2. 問題
    • HTTP 相關
      HTTP 與 HTTPS 區別,HTTPS 原理,如何加密
    • 談談閉包
    • 談談做用域鏈
    • 經常使用的跨域方式
    • vue
      • 特色
      • 生命週期
      • vuex
        實現原理(事件綁定)-如何實現
      • 與 react 的不一樣
        應用場景
      • 如何實現雙向綁定
      • 如何通訊
  3. 其餘
    • 還會哪些語言
    • 還有什麼感受沒問到但掌握很好的
    • 是否還有其餘的問題
    • 有什麼問題想要問的

二面

  • react
    屢次調用 setstate 爲何不立刻渲染
  • 解析 json ,手寫 parse 函數
  • csrf 舉例
  • 獲取dom節點方式
  • 將給定節點子元素第一個和最後一個元素替換
  • 端口號的做用

端口

IP地址讓網絡上的兩個節點之間能夠創建點對點的鏈接

端口號則爲端到端的鏈接提供了可能 (程序間通信的接口)

IP協議是由TCP、UDP、ARP、ICMP等一系列子協議組成的。其中

  • TCP和UDP協議

    主要用來作傳輸數據使用的

    在TCP和UDP協議中,都有端口號的概念存在

  • 端口號的做用

    主要是區分服務類別和在同一時間進行多個會話
    • 服務類別

      • 舉例來講,有主機A須要對外提供FTP和WWW兩種服務,若是沒有端口號存在的話,這兩種服務是沒法區分的。

        實際上,當網絡上某主機B須要訪問A的FTP服務時,就要指定目的端口號爲21;
        當須要訪問A的WWW服務時,則須要將目的端口號設爲80,這時A根據B訪問的端口號,就能夠區分B的兩種不一樣請求
    • 多個會話
      • 主機A須要同時下載網絡上某FTP服務器B上的兩個文件,那麼A須要 與B同時創建兩個會話,而這兩個傳輸會話就是靠源端口號來區分的。在這種狀況下若是沒有源端口號的概念,那麼A就沒法區分B傳回的數據到底是屬於哪一個會話,屬於哪一個文件
      • 通訊過程是,A使用本機的1025號端口請求B的21號端口上的文件1,同時又使用1026號端口請求文件2。對於返回的數據,發現是傳回給1025號端口的,就認爲是屬於文件1;傳回給1026號端口的,則認爲是屬於文件2。這就是端口號區分多個會話的做用。

在線編程——編寫一個 css 層級選擇器

根據一個給定的元素生成一個css 選擇器,函數名爲genCssSelector ,
點擊某元素彈出該元素及其父元素,相似 querySelector

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Document</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script language="javaScript">
        // your code here
        var genCssSelector = function (e) {
            e = e || window.event
            var tar = e.target || e.srcElement
            var objArr = []

            while (tar) {
                if (tar.id) { 
                    objArr.push('#' + tar.id) 
                    console.log('id')
                    return objArr.reverse().join(' ')                // 考慮 id 的惟一性,若是有 id,則中止查找
                }else if (tar.className) {
                    objArr.push('.' + tar.className.split(' ')[0])   // 考慮若是有多個 class
                }else {
                    objArr.push(tar.nodeName.toLowerCase())          
                }
                tar = tar.parentNode
            }
            objArr.pop()
            return objArr.reverse().join(' ')
        }

        document.addEventListener('click', function (e) {
            //點擊li時,返回:html body #page .content.main .refer ul li 
            console.log(genCssSelector(e));
        })
    </script>
</head>
<body>
    <div id="page">
        <div class="main" id="main">
            <div class="reference refer">
                <ul>
                    <li></li>
                    <li></li>
                    23333
                </ul>
            </div>
        </div>
    </div>
</body>
</html>

獲取 dom 元素

JS獲取DOM元素的方法(8種)

  • getElementById

    只獲取到一個元素,沒有找到返回null
  • getElementsByName
  • getElementsByTagName
  • getElementsByClassName
  • document.documentElement

    獲取html
  • document.body

    獲取body
  • querySelector

    獲取一個元素
  • querySelectorAll

    獲取一組元素

獲取子元素

  • childNodes
    dom.childNodes 返回一個nodeList(元素的全部子元素)
    • nodeType
      • 元素節點的nodeType屬性值爲1
      • 屬性節點的nodeType屬性值爲2
      • 文本節點的nodeType屬性值爲3
    • nodeValue屬性

      得到和改變文本節點的值
  • firstChild 第一個子元素
  • lastChild

獲取父、兄

  • parentNode
  • nextSibling
  • previousSbiling

建立元素

  • createDocumentFragment

    建立一個dom片斷
  • createElement

    建立一個具體的元素
  • createTextNode

    建立一個文本節點

增刪改元素

  • appendChild
  • removeChild
  • replaceChild
  • insertBefore

如何用 JS 實現 JSON.parse

---eval

直接調用eval

var json = '{"a":"1", "b":2}';
var obj = eval("(" + json + ")");    // obj 就是 json 反序列化以後獲得的對象

原理

JSON 脫胎於 JS,同時也是 JS 的子集,因此可以直接交給 eval 運行

  • 加上圓括號的目的是迫使eval函數在處理JavaScript代碼的時候強制將括號內的表達式(expression)轉化爲對象,而不是做爲語句(statement)來執行

    例如對象字面量{},如若不加外層的括號,那麼eval會將大括號識別爲JavaScript代碼塊的開始和結束標記,那麼{}將會被認爲是執行了一句空語句

缺點

  • XSS 漏洞

    如:參數 json 並不是真正的 JSON 數據,而是可執行的 JS 代碼
  • 對參數 json 作校驗,只有真正符合 JSON 格式,才能調用 eval
    ```js
    // 1. 用 4 個正則表達式分爲兩個階段解決(包容ie 和safari 的regexp 引擎)
    // 2. 將 json 反斜槓替換爲 '@' (non-json字符)
    // 3. 用 ']' 替換全部簡單標記
    // 4. 刪除全部跟隨冒號,逗號或文本開始的方括號
    // 5. 若是隻剩下 '] , { }' 則是安全的

    var rx_one = /^[],:{}\s]$/;
    var rx_two = /\(?:["\/bfnrt]|u[0-9a-fA-F]{4})/g;
    var rx_three = /"[^"\\\n\r]
    "|true|false|null|-?\d+(?:.\d)?(?:[eE][+-]?\d+)?/g;
    var rx_four = /(?:^|:|,)(?:\s
    [)+/g;

    if (
    rx_one.test(
    json
    .replace(rx_two, "@")
    .replace(rx_three, "]")
    .replace(rx_four, "")
    )
    ) {
    var obj = eval("(" +json + ")");
    }
    ```

---遞歸

第一種 eval 的方法,至關於一古腦兒把 JSON 字符串塞進去。
其實咱們還能夠手動逐個字符地掃描,而後進行判斷,這就是第二種方法:遞歸

// 所謂遞歸,就是重複調用value 函數
value = function () {

// Parse a JSON value. It could be an object, an array, a string, a number,
// or a word.

    white();
    // 根據當前字符是什麼,咱們便能推導出後面應該接的是什麼類型
    switch (ch) {
        case "{":
            return object();
        case "[":
            return array();
        case "\"":
            return string();
        case "-":
            return number();
        default:
            return (ch >= "0" && ch <= "9")
                ? number()
                : word();
    }
};

// 調用核心的 next 函數,逐個讀取字符
var next = function (c) {

// If a c parameter is provided, verify that it matches the current character.

    if (c && c !== ch) {
        error("Expected '" + c + "' instead of '" + ch + "'");
    }

// Get the next character. When there are no more characters,
// return the empty string.

    ch = text.charAt(at);
    at += 1;
    return ch;
};
  • 對於常量token false true null 進行匹配,不匹配返回錯誤

{"a":"1", "b":2} 爲例

程序大體邏輯是:啓動 → 首次調用 value() → 發現是 { → 原來是對象,走 object() → 經過 string() 獲得 key 值爲 "a" → 讀取到冒號,哦,後面多是對象、數組、布爾值等等,具體是什麼,還得再次調用 value() 才知道 → ……

xml 解析

  • close tag

    使用一個 nodeStack 棧,在 opentag 時推入節點,close tag 時檢查當前節點是否和棧尾節點是否匹配,匹配則推出末尾節點
  • comment

參考:JSON.parse 三種實現方式

react setState

  • setState 不保證同步

    • 可能會爲了性能收益批量執行
    • setState() 不會馬上改變 this.state,而是建立一個即將處理的 state 轉變。在調用該方法以後訪問 this.state 可能會返回現有的值。
    解決方案
    • 使用回調函數

      setState 方法接收一個 function 做爲回調函數。這個回掉函數會在 setState 完成之後直接調用,這樣就能夠獲取最新的 state
      js this.setState({ selection: value }, this.fireOnSelect)

    • setTimeout
      在 setState 使用 setTimeout 來讓 setState 先完成之後再執行裏面內容
      js this.setState({ selection: value }); setTimeout(this.fireOnSelect, 0);

  • 形成沒必要要的渲染
    • shouldComponentUpdate 解決

      setState() 將老是觸發一次重繪,除非在 shouldComponentUpdate() 中實現了條件渲染邏輯
    • 和渲染無關的狀態儘可能不要放在 state 中來管理

      一般 state 中只來管理和渲染有關的狀態 ,從而保證 setState 改變的狀態都是和渲染有關的狀態。這樣子就能夠避免沒必要要的重複渲染。其餘和渲染無關的狀態,能夠直接以屬性的形式保存在組件中,在須要的時候調用和改變,不會形成渲染。

  • 不能頗有效的管理全部的組件狀態

參考:淺談使用React.setState須要注意的三點

3. 百度

一面

jsonp cors

css

  • 分欄佈局哪些方式
  • 詳細說下flex

js & jq

  • 如何獲取一個元素(js jq)
  • 異步事件是如何發送的,經常使用機制
  • 有哪些接收後臺數據的方法
    • ajax
    • fetch
    • jsonp
    • websocket
    • SSE
  • event loop
  • 喜歡 es6 的哪些屬性
  • 箭頭函數與普通函數的不一樣
  • 閉包
    • 簡述
    • 應用
    • 在循環中如何用其餘方式代替閉包

vue

  • 和 react 區別
  • 如何向服務器傳遞數據

操做系統

  • 線程 && 進程

計算機網絡

  • 除了tcp 還用到哪些
  • http 與 tcp 分別屬於第幾層

數據結構

  • 有哪些線性存儲空間(array 棧)

二面

  • 如何作一個 css 選擇器

    見本文 阿里-在線編程
  • 給定一組dom 節點,和一個css樣式表,找出不含有樣式的dom

    面試官很耐心的解釋了,仍是沒聽明白題目
  • 鏈表操做
    • 單向鏈表反轉
  • 居中問題

    沒有詳細問,我分了兩個方面分別回答
    • 水平居中
    • 垂直水平
    詳細見 CSS 居中
  • get & post

    回答了大多數應聘者的 「標準答案」, 但經面試官指點,頓悟,大概這就叫高手吧

三面

  • 數字的存儲

  • 前端的編碼問題
    • 種類
    • 亂碼如何處理
  • 有哪些協議,分別有什麼做用
  • 關於實習經歷,找實習的過程,項目中的二三事及解決方案
  • 大學中最有成就感的事
  • 閒聊了一下,關於保研等等,總共 四十分鐘

分欄佈局

---等分佈局

  • float
    • 原理:增大父框的實際寬度後,使用CSS3屬性box-sizing進行佈局的輔助。

    • 用法:先將父框設置爲 margin-left: -*px,再設置子框 float: left、width: 25%、padding-left、box-sizing: border-box

      .parent{
          margin-left: -20px;
      }
      
      .column{
          float: left;
          width: 25%;
          padding-left: 20px;
          box-sizing: border-box;  /*包含padding區域 w+g*/
      }
  • table
    • 原理:經過增長一個父框的修正框,增大其寬度,並將父框轉換爲 table,將子框轉換爲 tabel-cell 進行佈局。

    • 用法:先將父框的修正框設置爲 margin-left: -*px,再設置父框 display: table、width:100%、table-layout: fixed,設置子框 display: table-cell、padding-left

      .parent-fix{
          margin-left: -20px;
      }
      .parent{
          display: table;
          width:100%;
          table-layout: fixed;
      }
      .column{
          display: table-cell;
          padding-left: 20px;
      }
  • flex
    • 原理:經過設置CSS3佈局利器flex中的flex屬性以達到等分佈局。

    • 用法:將父框設置爲display: flex,再設置子框flex: 1,最後設置子框與子框的間距margin-left。

如何獲取一個class

// 直接獲取---須要高版本瀏覽器支持
document.querySelectorAll("div.aa")

// 相似屬性選擇器的寫法
document.querySelectorAll("div[class='aa']")

// 補充一下還能夠not選擇器
document.querySelectorAll(".aa:not(ul)")

document.getElementsByClassName('cls')

// jq
$('.className')

Event Loop

js 單線程:
用途決定,操做 DOM

任務隊列

排隊緣由:計算量大的同步執行,IO設備(輸入輸出設備)很慢(好比Ajax操做從網絡讀取數據)異步。

異步任務指的是,不進入主線程、而進入"任務隊列"(task queue)的任務,只有"任務隊列"通知主線程,某個異步任務能夠執行了,該任務纔會進入主線程執行

"任務隊列"中的事件,除了IO設備的事件之外,還包括一些用戶產生的事件(好比鼠標點擊、頁面滾動等等)。只要指定過回調函數,這些事件發生時就會進入"任務隊列",等待主線程讀取。

  • 全部同步任務都在主線程上執行,造成一個執行棧(execution context stack)。

  • 主線程以外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。

  • 一旦"執行棧"中的全部同步任務執行完畢,系統就會讀取"任務隊列",看看裏面有哪些事件。那些對應的異步任務,因而結束等待狀態,進入執行棧,開始執行。

  • 主線程不斷重複上面的第三步。

只要主線程空了,就去檢查異步的任務隊列,若是異步事件觸發,則將其加到主線程的執行棧

深刻了解定時器

  • 零延遲 setTimeout(func, 0)

    零延遲並非意味着回調函數馬上執行。它取決於主線程當前是否空閒與「任務隊列」裏其前面正在等待的任務。
  • 調用setTimeout()以後,該方法會返回一直數值ID,表示超時調用。這個超時調用ID是計劃執行代碼的惟一標識符,能夠經過它來取消超時調用

  • 超時調用的代碼都是在全局做用域中執行的,所以函數中this的值在非嚴格模式下指向window對象,嚴格模式下是undefined。

Event Loop

異步與event loop沒有太直接的關係,準確的來說event loop 只是實現異步的一種機制
主任務 ——> micro task ——> 渲染視圖 ——> macro task

主線程從"任務隊列"中讀取事件,這個過程是循環不斷的,因此整個的這種運行機制又稱爲Event Loop(事件循環)

Javascript 中的事件循環是以任務爲單位的,將不少個待執行的任務串聯在一塊兒就造成了隊列 Task Queue,不少的隊列前後按順序執行任務就造成了 Event Loop

一個事件循環(EventLoop)中會有一個正在執行的任務(Task),而這個任務就是從 macrotask 隊列中來的。
當這個 macrotask 執行結束後,全部可用的 microtask 將會在同一個事件循環中執行
當這些 microtask 執行結束後還能繼續添加 microtask 一直到真個 microtask 隊列執行結束。

  • 一個事件循環(event loop)會有一個或多個任務隊列(task queue)

    task queue 就是 macrotask queue
  • 每個 event loop 都有一個 microtask queue
  • task queue == macrotask queue != microtask queue
  • 一個任務 task 能夠放入 macrotask queue 也能夠放入 microtask queue 中
  • 當一個 task 被放入隊列 queue(macro或micro) 那這個 task 就能夠被當即執行了

Micro Task

當咱們想以同步的方式來處理異步任務時候就用 microtask(好比咱們須要直接在某段代碼後就去執行某個任務,就像Promise同樣)

  • process.nextTick
  • promise
  • Object.observe
  • MutationObserver

Macro Task

  • setTimeout
  • setInterval
  • setImmediate
  • I/O

任務隊列中,在每一次事件循環中,從 macrotask 隊列開始執行,macrotask只會提取一個執行,而microtask會一直提取,直到microsoft隊列爲空爲止。

也就是說若是某個microtask任務被推入到執行中,那麼當主線程任務執行完成後,會循環調用該隊列任務中的下一個任務來執行,直到該任務隊列到最後一個任務爲止。而事件循環每次只會入棧一個macrotask,主線程執行完成該任務後又會檢查microtasks 隊列並完成裏面的全部任務後再執行macrotask的任務。

執行過程以下:

  • 主線程空閒時首先執行 micro
  • 以後從 macro 中提取一個 task 到主任務,完成後再次執行 micro queue(執行一個cycle)
  • 反覆過程2, 每一個週期爲一個事件循環

爲啥要用 microtask?

  • micro 執行總在 macro 以前
  • micro 所有執行完畢後會更新 UI 和執行下一個macro
    根據HTML Standard,在每一個 task 運行完之後,UI 都會重渲染,那麼在 microtask 中就完成數據更新,當前 task 結束就能夠獲得最新的 UI 了
// 驗證
(function () {
    const $test = document.getElementById('test')
    let counter = 0

    function func1() {
        $test.innerText = ++counter
        alert('func1')
    }

    function func2() {
        $test.innerText = ++counter
        alert('func2')
    }

    function func3() {
        $test.innerText = ++counter
        alert('func3')
    }

    function func4() {
        $test.innerText = ++counter
        alert('func4')
    }

    (function () {
        // main task
        func1()

        // macro task
        setTimeout(() => {
            func2()

            // micro task
            Promise.resolve().then(func4)
        }, 0);

        // macro task
        setTimeout(func1, 0);

        // micro task
        Promise.resolve().then(func3)

        // main task
        func4()
    })()

    // alert func1
    // alert func4
    // alert func3
    // UI update ---> counter = 3
    // alert func2
    // alert func4
    // UI update ---> counter = 5
    // alert func1
    // UI update ---> counter = 6
})()

接收後臺資源的方法(除了Ajax)

  • Ajax
  • fetch
    返回一個Promise對象, 根據 Promise Api 的特性, fetch能夠方便地使用then方法將各個處理邏輯串起來

    mode

    // fetch能夠設置不一樣的模式使得請求有效
    fetch(url, {mode: 'cors'});
  • Jsonp

  • websocket
    服務器推送技術之一
    全雙工
  • SSE(server-sent-events)
    單向通道(服務器 -> 瀏覽器)

異步編程經常使用方法

ES 6之前:

  • 回調函數
  • 事件監聽(事件發佈/訂閱)
  • Promise對象

ES 6:

  • Generator函數(協程coroutine)

ES 7:

  • async和await

回調函數

通常是須要在一個耗時操做以後執行某個操做時能夠使用回調函數

  • 定時器
  • 讀取文件

問題:
在回調函數以外沒法捕獲到回調函數中的異常

var fs = require('fs');

try{
    fs.readFile('not_exist_file', 'utf8', function(err, data){
        console.log(data);
    });
}
catch(e){
    console.log("error caught: " + e);
}

嘗試讀取一個不存在的文件,這固然會引起異常,可是最外層的try/catch語句卻沒法捕獲這個異常。這是異步代碼的執行機制致使的

爲何異步代碼回調函數中的異常沒法被最外層的try/catch語句捕獲?

異步調用通常分爲兩個階段,提交請求和處理結果,這兩個階段之間有事件循環的調用,它們屬於兩個不一樣的事件循環(tick),彼此沒有關聯。

異步調用通常以傳入callback的方式來指定異步操做完成後要執行的動做。而異步調用本體和callback屬於不一樣的事件循環。

try/catch語句只能捕獲當次事件循環的異常,對callback無能爲力。

事件監聽(訂閱-發佈)

典型的邏輯分離方式,對代碼解耦頗有用處
把不變的部分封裝在組件內部,供外部調用,須要自定義的部分暴露在外部處理。
從某種意義上說,事件的設計就是組件的接口設計。

//發佈和訂閱事件

var events = require('events');
var emitter = new events.EventEmitter();

emitter.on('event1', function(message){
    console.log(message);
});

emitter.emit('event1', "message for you");

Promise 對象

用同步操做的流程寫法來表達異步操做,避免了層層嵌套的異步回調

  • Promise.prototype.then()

    //原生Primose順序嵌套回調示例
    var fs = require('fs')
    
    var read = function (filename){
        var promise = new Promise(function(resolve, reject){
            fs.readFile(filename, 'utf8', function(err, data){
                if (err){
                    reject(err);
                }
                resolve(data);
            })
        });
        return promise;
    }
    
    read('./text1.txt')
    .then(function(data){
        console.log(data);
        return read('./text2.txt');   // 返回了一個新的Promise實例
    })
    .then(function(data){
        console.log(data);
    });
    Promise構造函數的參數是一個函數,在這個函數中咱們寫異步操做的代碼
    在異步操做的回調中,根據err變量來選擇是執行resolve方法仍是reject方法
    • 通常來講調用resolve方法的參數是異步操做獲取到的數據(若是有的話),但還多是另外一個Promise對象,表示異步操做的結果有多是一個值
    • 也有多是另外一個異步操做,調用reject方法的參數是異步回調用的err參數

調用read函數時,實際上返回的是一個Promise對象,經過在這個Promise對象上調用then方法並傳入resolve方法和reject方法來指定異步操做成功和失敗後的操做。

  • Promise.prototype.catch()

    用於指定發生錯誤時的回調函數

    read('./text1.txt')
    .then(function(data){
        console.log(data);
        return read('not_exist_file');
    })
    .then(function(data){
        console.log(data);
    })
    .catch(function(err){
        console.log("error caught: " + err);
    })
    .then(function(data){
        console.log("completed");
    })

    使用Promise對象的catch方法能夠捕獲異步調用鏈中callback的異常
    Promise對象的catch方法返回的也是一個Promise對象,所以,在catch方法後還能夠繼續寫異步調用方法

  • Promise異步併發
    • Promise.all()
      • 將多個Promise實例,包裝成一個新的Promise實例
        var p = Promise.all([p1,p2,p3]);
      • 接受一個數組做爲參數,p一、p二、p3都是Promise對象實例
      • 只有p一、p二、p3的狀態都變成fulfilled,p的狀態纔會變成fulfilled,此時p一、p二、p3的返回值組成一個數組,傳遞給p的回調函數。
      • 只要p一、p二、p3之中有一個被rejected,p的狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調函數。
        ```js
        var promises = [1, 2].map(function(fileno){
        return read('./text' + fileno + '.txt');
        });

        Promise.all(promises)
        .then(function(contents){
        console.log(contents);
        })
        .catch(function(err){
        console.log("error caught: " + err);
        })
        ```
    • Promise.race()
      • 將多個Promise實例,包裝成一個新的Promise實例
        var p = Promise.race([p1,p2,p3]);
      • p一、p二、p3只要有一個實例率先改變狀態,p的狀態就會跟着改變,那個率先改變的Promise實例的返回值,就傳遞給p的返回值。
      • 若是Promise.all方法和Promise.race方法的參數不是Promise實例,就會先調用下面講到的Promise.resolve方法,將參數轉爲Promise實例,再進一步處理
    • Promise.resolve()
      • 將現有對象轉換成Promise對象
      var p = Promise.resolve('Hello');
      p.then(function (s){
          console.log(s)
      });
    • Promise.reject()
      • 返回一個新的Promise實例,該實例的狀態爲rejected。
      • Promise.reject 方法的參數reason,會被傳遞給實例的回調函數。
      var p = Promise.reject('出錯了');
      p.then(null, function (s){
          console.log(s)
      });
  • Generator函數
    • 能夠交出函數的執行權(暫停執行)
    • 整個Generator函數就是一個封裝的異步任務,或者說是異步任務的容器。異步操做須要暫停的地方,都用yield語句註明。

      function* gen(x){
          var y = yield x + 2;
          return y;
      }
      
      var g = gen(1);
      var r1 = g.next(); // { value: 3, done: false }
      console.log(r1);
      var r2 = g.next() // { value: undefined, done: true }
      console.log(r2);

    **Generator函數的函數名前面有一個"*"**

    • 調用Generator函數,會返回一個內部指針(即遍歷器)g,這是Generator函數和通常函數不一樣的地方,調用它不會返回結果,而是一個指針對象。
    • 調用指針g的next方法,會移動內部指針,指向第一個遇到的yield語句
      • next方法的做用是分階段執行Generator函數。每次調用next方法,會返回一個對象,表示當前階段的信息(value屬性和done屬性)
      • value屬性是yield語句後面表達式的值,表示當前階段的值;
      • done屬性是一個布爾值,表示Generator函數是否執行完畢,便是否還有下一個階段
  • Thunk 函數
    Thunk 函數的含義和用法
  • ES 7中的async和await

  • fetch
    • 替代瀏覽器原生的XMLHttpRequest異步請求

來自深刻解析Javascript異步編程

get & post 剖析

入門回答

區別:

  • get
    • 參數包含在 URL 中
    • 大小有限制
    • 使用Request.QueryString 獲取變量的值
    • 安全性差,直觀顯示
  • post
    • 經過 request body 傳遞參數
    • 經過 Request.Form 獲取變量的值

當我滿心充滿着自信和喜悅時,彷彿看到了面試官眉頭一皺,So?

「標準答案」
aspect GET POST
瀏覽器回退 無影響 回退會再次提交請求
地址標記 產生的 URL 地址能夠被 Bookmark 提交地址不被標記
cache 該請求會被瀏覽器主動 cache 該請求不會被緩存
編碼 只能進行url編碼 支持多種編碼方式
參數保留 請求參數會被完整保留在瀏覽器歷史記錄裏 POST中的參數不會被保留
長度限制 有(瀏覽器限制,IE-2083個字符) 無(限制做用的是服務器的處理程序的處理能力)
參數類型 只接受ASCII字符 沒有限制
參數傳遞 經過URL傳遞 放在Request body中
裸奔剖析

99%的人都理解錯了HTTP中GET與POST的區別

前端編碼

字符 表示 補充
二進制 0/1 八個二進制位能夠組合出256種狀態,這被稱爲一個字節(byte)
八進制 0~7
十進制 0~9
十六禁止 0~9 A~F
  • 8byte = 1bit
  • 1024 字節 = 1k
  • 1024k = 1M
  • 1024M = 1G
  • 1024G = 1T
編碼 特徵 補充
二十一進制碼(BCD碼) 保留了十進制數的權,而數字則用二進制數碼0和1的組合來表示 在須要高精度的計算中BCD編碼比較經常使用(瞭解)
ASCII碼 美國信息交換標準委員會制定的7位字符編碼,用7位二進制碼錶示一個字符,第8 位用於肯定附加的128 個特殊符號字符、外來語字母和圖形符號
GB2312 爲了保存非英文,使用127號以後的空位保存新的字母(一個8位的字節能夠組合256種狀態,ASCII只編到127號),一直編到最後一位255,並且不一樣國家表示的符號也不同,也能夠說GB2312是對ASCII的中文擴展 不夠用,後來只要求只要第一個字節是大於127就固定表示這是一個漢字的開始,稱之爲GBK編碼
GB18030 / DBCS 編碼中又增長了幾千個新的少數民族的字,GBK擴展成了GB18030統稱它們叫作DBCS
Unicode ISO(國際標準化組織)廢棄了全部地區性編碼方案,作了一套包括了地球上全部文化、符號以及字母的編碼;ISO規定:必須用兩個字節,16位來統一表示全部的字符,不管是半角的英文字母,仍是全角的漢字,它們都是統一的一個字符!也就是兩個字節
UTF-8 UTF-8 互聯網上使用最廣的一種 Unicode 的實現方式,每次以8個位爲單位傳輸數據;UTF-16就是每次 16 個位 UTF-8 最大的一個特色,就是它是一種變長的編碼方式,Unicode一箇中文字符佔 2 個字節,而UTF-8一箇中文字符佔3個字節,UTF-8是Unicode的實現方式之一

進制轉換

------十進制轉其餘-------
var a = 24;
a.toString(2);//11000
a.toString(8);//30
a.toString(16);//18
------其餘轉十進制-------
var b=11000,c=30,d=18;
console.log(parseInt(b, 2)); // 二進制轉十進制
console.log(parseInt(c, 8)); // 八進制轉十進制
console.log(parseInt(d, 16));// 十六進制轉十進制

前端編碼問題

在使用nodeJS編寫前端工具時,對文本文件的操做比較多,這就涉及到了文件的編碼問題,經常使用的文本編碼有UTF8和GBK兩種,而且UTF8文件還可能帶有BOM(字節順序標記),在讀取不一樣編碼的文本文件時,須要將文件內容轉換爲JS使用的UTF8編碼字符串後才能正常處理

  • 移除 BOM

    BOM用於標記一個文本文件使用Unicode編碼,其自己是一個Unicode字符("\uFEFF"),位於文本文件頭部以告訴其餘編輯器以utf8來顯示字符

    可是在網頁上並不須要添加BOM頭識別,由於網頁上能夠使用 head頭 指定charset=utf8告訴瀏覽器用utf8來解釋.可是你用window自動的編輯器,編輯,而後有顯示在網頁上這樣就會顯示出0xEF 0xBB 0xBF這3個字符。這樣網頁上就須要去除0xEF 0xBB 0xBF
    • 能夠使用editplus 選擇不帶BOM的編碼,這樣就能夠去除了
    • js 去除

      // 能夠經過文件頭的幾個字節來判斷文件是否包含BOM以及使用哪一種Unicode,若是讀取文件的時候不去掉BOM
      // 假如咱們將幾個JS文件合併成一個,若是文件中含有BOM字符,就會致使語法錯誤
      // 因此咱們用 nodeJS讀取文件是通常先去掉BOM
      
      var bin = fs.readFileSync(pathname);//經過node 中fs模塊同步讀文件內容
      //判斷文件頭的字節
      if (bin[0] === 0xEF && bin[1] === 0xBB && bin[2] === 0xBF) {
          bin = bin.slice(3);
      }
  • GBK 轉 UTF8

    NodeJS支持在讀取文本文件時,或者在Buffer轉換爲字符串時指定文本編碼,但GBK編碼不在NodeJS自身支持範圍內,通常咱們藉助iconv-lite這個三方包來轉換編碼,首先使用npm下載這個第三方包,讀取GBK文件函數以下:

    var iconv = require('iconv-lite');
    function readGBKText(pathname) {
        var myFs = fs.readFileSync(pathname);
        return iconv.decode(myFs, 'gbk');
    }

數據結構

經常使用的線性結構有:線性表,棧,隊列,循環隊列,數組
線性表中包括順序表、鏈表等,其中:

  • 棧和隊列只是屬於邏輯上的概念,實際中不存在,僅僅是一種思想,一種理念;
  • 線性表則是在內存中數據的一種組織、存儲的方式。

常見的排序算法及其時間複雜度

參考:十大經典排序算法總結(JavaScript描述)

其餘

  • git 與 GitHub 有什麼區別
  • git 的一些指令
  • Linux

計算機網絡

**若有不足,歡迎交流,祝各位看官 offer 拿到手軟 O(∩_∩)O**

個人博客即將搬運同步至騰訊雲+社區,邀請你們一同入駐:https://cloud.tencent.com/developer/support-plan

相關文章
相關標籤/搜索