2019年前端面試題-03

  1. let與var的區別?
    Let爲ES6新添加申明變量的命令,它相似於var,可是有如下不一樣:
    一、var聲明的變量,其做用域爲該語句所在的函數內,且存在變量提高現象
    二、let聲明的變量,其做用域爲該語句所在的代碼塊內,不存在變量提高
    三、let不容許重複聲明.
  2. 封裝一個函數,參數是定時器的時間,.then執行回調函數。javascript

    function sleep (time) { 
    return new Promise((resolve) => setTimeout(resolve, time));
    }
  3. 項目作過哪些性能優化?
    一、減小HTTP請求數
    二、減小DNS查詢
    三、使用CDN
    四、避免重定向
    五、圖片懶加載
    六、減小DOM元素數量
    七、減小DOM操做
    八、使用外部JavaScript和CSS
    九、壓縮JavaScript、CSS、字體、圖片等
    十、優化CSS Sprite
    十一、使用iconfont
    十二、字體裁剪
    1三、多域名分發劃份內容到不一樣域名
    1四、儘可能減小iframe使用
    1五、避免圖片src爲空
    1六、把樣式表放在 中
    1七、把腳本放在頁面底部
  4. 怎麼判斷兩個對象相等?
    一、轉化成字符串後比較字符串是否一致:php

    JSON.stringify(obj)===JSON.stringify(obj2);

    二、Object.is(obj1,obj2):判斷兩個值是否 [相同]。若是下列任何一項成立,則兩個值相同。css

    * 兩個值都是 [undefined]
       * 兩個值都是 [null]
       * 兩個值都是true或者都是false
       * 兩個值是由相同個數的字符按照相同的順序組成的字符串
       * ~兩個值指向同一個對象~
       * 兩個值都是數字而且
           * 都是正零+0
           * 都是負零-0
           * 都是 [NaN]
           * 都是除零和[NaN]外的其它同一個數字
  5. 什麼是模塊化開發?

    實現mvvm主要包含兩個方面,數據變化更新視圖,視圖變化更新數據:
    圖片描述html

    關鍵點在於data如何更新view,由於view更新data其實能夠經過事件監聽便可,好比input標籤監聽 'input' 事件就能夠實現了。因此咱們着重來分析下,當數據改變,如何更新視圖的。
    數據更新視圖的重點是如何知道數據變了,只要知道數據變了,那麼接下去的事都好處理。如何知道數據變了,其實上文咱們已經給出答案了,就是經過Object.defineProperty( )對屬性設置一個set函數,當數據改變了就會來觸發這個函數,因此咱們只要將一些須要更新的方法放在這裏面就能夠實現data更新view了。前端

    Vue是經過Object.defineProperty()來實現數據劫持的。它能夠來控制一個對象屬性的一些特有操做,好比set()、get()、是否能夠枚舉。
    圖片描述
    實現數據的雙向綁定,首先要對數據進行劫持監聽,因此咱們須要設置一個監聽器Observer,用來監聽全部屬性。若是屬性發上變化了,就須要告訴訂閱者Watcher看是否須要更新。由於訂閱者是有不少個,因此咱們須要有一個消息訂閱器Dep來專門收集這些訂閱者,而後在監聽器Observer和訂閱者Watcher之間進行統一管理的。接着,咱們還須要有一個指令解析器Compile,對每一個節點元素進行掃描和解析,將相關指令對應初始化成一個訂閱者Watcher,並替換模板數據或者綁定相應的函數,此時當訂閱者Watcher接收到相應屬性的變化,就會執行對應的更新函數,從而更新視圖。所以接下去咱們執行如下3個步驟,實現數據的雙向綁定:
    1.實現一個監聽器Observer,用來劫持並監聽全部屬性,若是有變更的,就通知訂閱者。
    2.實現一個訂閱者Watcher,能夠收到屬性的變化通知並執行相應的函數,從而更新視圖。
    3.實現一個解析器Compile,能夠掃描和解析每一個節點的相關指令,並根據初始化模板數據以及初始化相應的訂閱器。java

    流程圖以下:
    圖片描述面試

  6. 瀏覽器兼容性問題
    圖片描述
    一、Normalize.css
    二、不一樣瀏覽器的標籤默認的外邊距和內邊距不一樣:
    三、IE6雙邊距問題:在 IE6中設置了float , 同時又設置margin , 就會出現邊距問題:設置display:inline;
    四、圖片默認有間距:使用float 爲img 佈局
    五、IE9如下瀏覽器不能使用opacity:ajax

    opacity: 0.5;
    filter: alpha(opacity = 50);
    filter: progid:DXImageTransform.Microsoft.Alpha(style = 0, opacity = 50);

    六、cursor:hand 顯示手型在safari 上不支持:統一使用 cursor:pointer
    七、當標籤的高度設置小於10px,在IE六、IE7中會超出本身設置的高度:超出高度的標籤設置overflow:hidden,或者設置line-height的值小於你的設置高度
    八、CSS HACK的方法:json

    height: 100px;    // 全部瀏覽器 通用 
    _height: 100px;    // IE6 專用 
    *+height: 100px;    // IE7 專用 
    *height: 100px;    // IE六、IE7 共用 
    height: 100px !important;        // IE七、FF 共用

    代碼的順序必定不能顛倒了,要不又前功盡棄了。由於瀏覽器在解釋程序的時候,若是重名的話,會用後面的覆蓋前面的,就象給變量賦值一個道理,因此咱們把通用的放前面,越專用的越放後面segmentfault

  7. 前端跨域

    1. 什麼是跨域?

      >     只要協議、域名、端口有任何一個不一樣,都被看成是不一樣的域。
      >     同源策略是瀏覽器的行爲,是爲了保護本地數據不被JavaScript代碼獲取回來的數據污染,所以攔截的是客戶端發出的請求回來的數據接收,即請求發送了,服務器響應了,可是沒法被瀏覽器接收。
      >     之因此會跨域,是由於受到了同源策略的限制,同源策略要求源相同才能正常進行通訊,即協議、域名、端口號都徹底一致。
      > 
      > 注意點:
      > 若是是協議和端口形成的跨域問題「前臺」是無能爲力的;
      > 在跨域問題上,域僅僅是經過「URL的首部」來識別而不會去嘗試判斷相同的ip地址對應着兩個域或兩個域是否在同一個ip上。 (「URL的首部」指window.location.protocol +window.location.host,也能夠理解爲「Domains, protocols and ports must match」。)
    2. 什麼是同源策略?

      > 所謂同源是指,域名,協議,端口相同。瀏覽器採用同源策略,就是禁止頁面加載或執行與自身來源不一樣的域的任何腳本。
    3. 經過document.domain跨域(只適用於不一樣子域的框架間的交互)

      瀏覽器有一個同源策略,其限制之一是不能經過ajax的方法去請求不一樣源中的文檔。第二個限制是瀏覽器中不一樣域的框架之間是不能進行js的交互操做的。不一樣的框架之間是能夠獲取window對象的,但卻沒法獲取相應的屬性和方法。好比,有一個頁面,它的地址是 [www.damonare.cn/a.html], 在這個頁面裏面有一個iframe,它的src是 [damonare.cn/b.html], 很顯然,這個頁面與它裏面的iframe框架是不一樣域的,因此咱們是沒法經過在頁面中書寫js代碼來獲取iframe中的東西的:
    4. 經過location.hash跨域
    5. 經過HTML5的postMessage方法跨域
    6. 經過jsonp跨域

      JSONP的優缺點
          * JSONP的優勢是:它不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中均可以運行,不須要XMLHttpRequest或ActiveX的支持;而且在請求完畢後能夠經過調用callback的方式回傳結果。
          * JSONP的缺點則是:它只支持GET請求而不支持POST等其它類型的HTTP請求;它只支持跨域HTTP請求這種狀況,不能解決不一樣域的兩個頁面之間如何進行JavaScript調用的問題。
    7. 經過CORS跨域

      CORS(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與服務器應該如何溝通。CORS背後的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功仍是失敗。目前,全部瀏覽器都支持該功能,IE瀏覽器不能低於IE10。整個CORS通訊過程,都是瀏覽器自動完成,不須要用戶參與。對於開發者來講,CORS通訊與同源的AJAX通訊沒有差異,代碼徹底同樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。
    8. 經過window.name跨域

      window對象有個name屬性,該屬性有個特徵:即在一個窗口(window)的生命週期內,窗口載入的全部的頁面都是共享一個window.name的,每一個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的全部頁面中的,並不會因新頁面的載入而進行重置。
  8. 前端優化:瀏覽器緩存

    前端優化:瀏覽器緩存技術介紹 - 掘金
    瀏覽器緩存分爲強緩存和協商緩存。

    當客戶端請求某個資源時,獲取緩存的流程以下:
    1)瀏覽器在加載資源時,先根據這個資源的一些http header判斷它是否命中強緩存,強緩存若是命中,瀏覽器直接從本身的緩存中讀取資源,不會發請求到服務器。好比:某個css文件,若是瀏覽器在加載它所在的網頁時,這個css文件的緩存配置命中了強緩存,瀏覽器就直接從緩存中加載這個css,連請求都不會發送到網頁所在服務器;

    2)當強緩存沒有命中的時候,瀏覽器必定會發送一個請求到服務器,經過服務器端依據資源的另一些http header驗證這個資源是否命中協商緩存,若是協商緩存命中,服務器會將這個請求返回,可是不會返回這個資源的數據,而是告訴客戶端能夠直接從緩存中加載這個資源,因而瀏覽器就又會從本身的緩存中去加載這個資源;

    3)強緩存與協商緩存的共同點是:若是命中,都是從客戶端緩存中加載資源,而不是從服務器加載資源數據;區別是:強緩存不發請求到服務器,協商緩存會發請求到服務器。

    4)當協商緩存也沒有命中的時候,瀏覽器直接從服務器加載資源數據。

  9. jsonp的原理與實現

    Jsonp是一種跨域通訊的手段,它的原理其實很簡單:

    > 1. 首先是利用script標籤的src屬性來實現跨域。
       > 2. 經過將前端方法做爲參數傳遞到服務器端,而後由服務器端注入參數以後再返回,實現服務器端向客戶端通訊。
       > 3. 因爲使用script標籤的src屬性,所以只支持get方法

    實現流程:

    一、設定一個script標籤

    <script src="http://jsonp.js?callback=xxx"></script>

    二、callback定義了一個函數名,而遠程服務端經過調用指定的函數並傳入參數來實現傳遞參數,將function(response)傳遞迴客戶端

    $callback = !empty($_GET['callback']) ? $_GET['callback'] : 'callback';
    echo $callback.'(.json_encode($data).)';

    三、客戶端接收到返回的js腳本,開始解析和執行function(response)

    簡單的實例:
    一個簡單的jsonp實現,其實就是拼接url,而後將動態添加一個script元素到頭部。

    function jsonp(req){
        var script = document.createElement('script');
        var url = req.url + '?callback=' + req.callback.name;
        script.src = url;
        document.getElementsByTagName('head')[0].appendChild(script); 
    }

    前端js示例:

    function hello(res){
        alert('hello ' + res.data);
    }
    jsonp({
        url : '',
        callback : hello 
    });

    服務器端代碼:

    var http = require('http');
    var urllib = require('url');
    
    var port = 8080;
    var data = {'data':'world'};
    
    http.createServer(function(req,res){
        var params = urllib.parse(req.url,true);
        if(params.query.callback){
            console.log(params.query.callback);
            //jsonp
            var str = params.query.callback + '(' + JSON.stringify(data) + ')';
            res.end(str);
        } else {
            res.end();
        }
        
    }).listen(port,function(){
        console.log('jsonp server is on');
    });

    可靠的jsonp實例:

    (function (global) {
        var id = 0,
            container = document.getElementsByTagName("head")[0];
    
        function jsonp(options) {
            if(!options || !options.url) return;
    
            var scriptNode = document.createElement("script"),
                data = options.data || {},
                url = options.url,
                callback = options.callback,
                fnName = "jsonp" + id++;
    
            // 添加回調函數
            data["callback"] = fnName;
    
            // 拼接url
            var params = [];
            for (var key in data) {
                params.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
            }
            url = url.indexOf("?") > 0 ? (url + "&") : (url + "?");
            url += params.join("&");
            scriptNode.src = url;
    
            // 傳遞的是一個匿名的回調函數,要執行的話,暴露爲一個全局方法
            global[fnName] = function (ret) {
                callback && callback(ret);
                container.removeChild(scriptNode);
                delete global[fnName];
            }
    
            // 出錯處理
            scriptNode.onerror = function () {
                callback && callback({error:"error"});
                container.removeChild(scriptNode);
                global[fnName] && delete global[fnName];
            }
    
            scriptNode.type = "text/javascript";
            container.appendChild(scriptNode)
        }
    
        global.jsonp = jsonp;
    
    })(this);

    使用示例:

    jsonp({
        url : "www.example.com",
        data : {id : 1},
        callback : function (ret) {
            console.log(ret);
        }
    });

歡迎閱讀:
2019年前端面試題-01
2019年前端面試題-02
2019年前端筆試題


我是Cloudy,年輕的前端攻城獅一枚,愛專研,愛技術,愛分享。
我的筆記,整理不易,感謝閱讀、點贊和收藏。
文章有任何問題歡迎你們指出,也歡迎你們一塊兒交流前端各類問題!
相關文章
相關標籤/搜索