耗時一週整理的前端面試題,乾貨爲主

websocket

Websocket同http同樣都是是基於tcp的,可靠性的雙向通訊協議,是創建在tcp之上的,而且是持久化的協議。css

websocket 和http區別?

  • 相同點html

    • 都是應用層的協議
    • 都是基於tcp,可靠的協議
  • 不一樣點node

    • websocket是持久化的協議.
    • websocket是雙向通訊協議,模擬socket協議,能夠雙向發送信息,而HTTP是單向的
    • websocket能夠在服務器端主動向客戶端發送信息,而http的服務端,只能經過客戶端主動請求

請描述一下cookie、sessionStorage和localStorage的區別?

  • 相同點:都存儲在客戶端
  • 不一樣點git

    1. 存儲大小
      cookie數據大小不能超過4k。
      sessionStorage和localStorage 雖然也有存儲大小的限制,但比cookie大得多,能夠達到5M或更大。
    2. 有效時間
      localStorage 存儲持久數據,瀏覽器關閉後數據不丟失除非主動刪除數據;
      sessionStorage 數據在當前瀏覽器窗口關閉後自動刪除。
      cookie 設置的cookie過時時間以前一直有效,即便窗口或瀏覽器關閉
    3. 數據與服務器之間的交互方式
      cookie的數據會自動的傳遞到服務器,服務器端也能夠寫cookie到客戶端
      sessionStorage和localStorage不會自動把數據發給服務器,僅在本地保存

JS的類型?

  • 基本類型github

    • undefined
    • null
    • Number
    • String
    • Boolean
  • 複雜類型web

    • Object

js變量按照存儲方式區分,有哪些類型,並表述其特色

  • 值類型:面試

    • undefined string number Boolean
    • 拷貝形式,
  • 引用類型:ajax

    • array , function
    • 指針指向,共用空間
    • 可無限擴展屬性,極大節省命名空間。
  • 特殊引用類型:function正則表達式

    • 同引用類型↑
    • 特殊引用類型只有function,因爲function的特殊性,使得它有點不一樣

JS中的typeof能獲得的那些類型? 6種

  • number
  • string
  • undefined
  • object : null和數組 都是object
  • function
  • boolean

注意:typeof沒法詳細區分引用類型的類型,除了function. 只能準確區分值類型的類型
好比:算法

typeof {} //object
 typeof [] //object
 typeof null //object
 typeof console.log // function

function是一個比較特殊的類型,因此typeof可以區分

什麼時候使用===什麼時候使用==?

  • 儘量使用 === 緣由以下

    • 一致性:使用 ==對一致性沒有任何好處,因此提早避免
    • 通常來講,===是最簡單的操做符,由於它不用類型轉換,因此相對來講,速度也會更快。
    • == 會進行類型轉換,很容易懵逼
  • == 的使用狀況,可參考

    • 判斷對象的屬性是否存在
    var obj = {};
        if( obj.a == null ){
            //這裏相對於:obj.a === null || obj.a === undefined 的簡寫形式,JQ源碼的推薦寫法
        }
    • 判斷函數的參數是否存在
    function fn( a, b){
            if( b == null ){
                //這裏至關於 b===null || b === undefined 的簡寫
            }
        }

如何理解JSON?

  • 從純JS的角度看,JSON就是對象,而且只有兩個API

    JSON.stringify({a:10,b:30}) //將對象轉爲字符串
       JSON.parse('{"a":10,"b":30}') //將JSON格式的字符串轉爲 對象
  • JSON也是一種輕量級的文本數據交換格式.

js中有哪些內置函數 9 種

  • Object
  • Array
  • Boolean
  • Number
  • String
  • Function
  • Date
  • RegExp
  • Error

判斷一個變量會被當作 true 仍是 false

var a = 100; console.log( !!a ); //true

window.onload和DOMContentLoaded的區別?

  • window.onload: 頁面中全部數據加載完成後,纔會執行,包括圖片,css等
  • DOMContentLoaded: DOM結構加載完成後執行,須要等待圖片等其餘資源加載完成

簡述如何實現一個模塊加載器,實現相似requires.js的基本功能

可參看這篇博文:https://github.com/youngwind/...

實現數組的隨機排序

//該方法最簡單,效果通常,每一個元素仍然有很大機率在它原來的位置附近出現
 arr.sort(function () { 
      return Math.random() - 0.5; 
   });

//Fisher–Yates shuffle費雪耶茲隨機置亂算法) !!!推薦

//算法思想:從0~i(i的變化爲 n-1到0遞減)中隨機取得一個下標,和最後一個元素(i)交換。
   var arr = [5,8,59,56];
   function shuffle(arr) { 
    var i = arr.length, t, j; 
    while (i) 
    { 
        j = Math.floor(Math.random() * i--);
        t= arr[i];
        arr[i] = arr[j];
        arr[j]= t;
    } 
} 
shuffle(arr)
console.log(arr);//[56, 8, 5, 59]

原型和原型鏈

什麼叫原型鏈

原型鏈是針對構造函數的,好比我建立了一個函數並經過變量new了一個函數,那這個函數就會繼承建立處理函數的屬性,若是訪問這個函數的屬性時,並無在new處理的變量中寫該屬性,那麼就會往上,根據protype逐級向上查找,這個查找的過程就叫原型鏈。

原型規則

  1. 全部的引用類型(數組,對象,函數),都具備對象的特殊,便可自由擴展屬性(除了Null,純屬意外)
  2. 全部的引用類型(數組,對象,函數),都有一個__proto__屬性,也能夠稱爲隱式原型,屬性值是一個普通的對象
  3. 全部的函數,都有一個prototype屬性,也可稱之爲顯式原型,屬性值是一個普通的對象
  4. 全部的引用類型(數組,對象,函數),__proto__屬性值指向它的構造函數的prototype屬性值
  5. 當試圖獲得一個對象的某個屬性時,若是這個對象自己沒有這個屬性,那麼會去它的__proto__中去找。

因爲它的隱式原型等於它的顯式原型,因此也會去 prototype 中去找。

構造函數

function Foo(name,age){
    this.name = name;
    this.age = age;
}
var foo = new Foo('h1',25);
var foo2 = new Foo('h1',250);
console.log(foo,foo2);

//循環對象自身的屬性
var item;
for( item in foo)
{
    //只遍歷對象自身的屬性,過濾掉該對象的顯式原型
    if(foo.hasOwnProperty(item))
    {
        console.log(item)
    }

}

描述new一個對象的過程

  1. 建立一個對象
  2. this指向這個新對象
  3. 執行代碼,即對this賦值
  4. return this。 默認有return,不用寫

如何判斷一個變量是數組類型

var arr = [1,2,3];
console.log(Array.isArray(arr)); //true

//instanceof運算符用於測試構造函數的prototype屬性是否出如今對象的原型鏈中的任何位置
console.log( arr instanceof Array) //true

寫一個原型繼承的例子

function Elem(id){
    this.dom = document.getElementById(id);
}

Elem.prototype.html = function(val){
    var dom = this.dom;
    if(val){
        dom.innerHTML = val;
        return this; //用來鏈式調用
    }else{
        return dom.innerHTML;
        
    }
}

Elem.prototype.on = function(type ,fn){
    var dom = this.dom;
    dom.addEventListener( type , fn);
    
}
var h1 = new Elem('h1');
h1.html("你被修改了").on('click', function(){
    console.log(this)
})

做用域和閉包

什麼叫做用域?

`做用域是針對變量的,好比我建立了一個函數,這個函數中包含了另一個函數。那麼該變量中就有3個做用域
全局做用域》函數做用域》內層函數的做用域
做用域的特色就是,先在本身的變量範圍中查找,若是找不到,就會沿着做用域往上找。
`

變量提高的理解

  • 變量定義
  • 函數聲明(注意和函數表達式的區別)
  • 預解析

this的使用場景

注意:this要在執行時才能確認值,定義時沒法確認

  • 做爲構造函數執行
  • 做爲對象屬性執行
  • 做爲普通函數執行
  • call apply bind
function f1(name,age){
    console.log(name,age)
    console.log(this); //this爲x對象
 }

f1.apply({x:'我是this'}, ["seek",20]);
f1.call({x:'我是this'}, "seek",20);


//使用bind改變this時,需用函數表達式
var f1 = function (name,age){
    console.log(name,age)
    console.log(this); //this爲x對象
}.bind('我是被綁定的this')

f1("seek",20)

閉包

`當一個函數的返回值是另一個函數,而返回的那個函數若是調用了其父函數內部的其它變量,
若是返回的這個函數在外部被執行,就產生了閉包。
表現形式:使函數外部可以調用函數內部定義的變量。`

  • 閉包的使用場景

    1. 函數做爲返回值

      function fn(){
          var a = 10;
          return function(){
              console.log(a); //a是自由變量,從父做用域開始找。
          }
      }
      var f1 =  fn();
      var a = 20;
      f1(); //10
    2. 函數做爲參數來傳遞

      function fn(){
          var a = 10;
          return function(){
              console.log(a); 
              }
      }
      var fn1 = fn();
      
      function fn2(fn){
          var a =20;
          fn();
      }
      fn2(fn1); //10

如何理解做用域?

  • 自由變量
  • 做用域鏈,即自由變量的查找
  • 閉包的兩個場景

JS建立10個a標籤,點擊時彈出對應的序號 (考點:做用域)

var str,a;
for( a=0; a<10;a++){
    str = document.createElement("a");
    str.innerHTML = a + "點我" + "<br/>";
    
    document.body.appendChild(str);
    
    (function(a){
        str.addEventListener("click",function(e){
            e.preventDefault();
            console.log(a)
        })
    })(a)
}

什麼叫異步,什麼叫同步?

同步是阻塞模式,異步是非阻塞模式。

  • 異步:不須要等操做作完,就響應用戶請求. 好比:ajax,img的加載,setTimeout,setInterval
  • 同步:必須等待操做作完,才返回結果.

數組API

var arr= [2,3,9,0];
  • forEach 遍歷全部元素
arr.forEach(function(item,index){
        console.log(item) // 2390
        console.log(index) //0123

    })
  • every 判斷全部元素是否都符合條件
var result = arr.every(function(item,index){
        if(item < 4)
        {
          return true;
        }
    })
  console.log(result); //false, 由於9並不小於4
  • some 判斷是否有至少一個元素符合條件
var result =  arr.some(function(item,index){
        if(item < 4)
        {
          return true;
        }
      })
console.log(result); //true 由於2,3,0小於4
  • sort 排序
var result =  arr.sort(function(a,b){
          // return a-b; //正序
          return b-a; // 倒序
        // return return Math.random() - 0.5; //最簡單的隨機數組排序,並不推薦

      })
console.log(result); //  [9, 3, 2, 0]
  • map 對元素從新組裝,生成新數組
//map適用範圍仍是較廣的,學會思考
 var result =  arr.map(function(item,index){
            return '<h1>' + item + '</h1>';
      })
console.log(result);   //  ["<h1>2</h1>", "<h1>3</h1>", "<h1>9</h1>", "<h1>0</h1>"]
  • filter 過濾符合條件的元素,較爲經常使用
var result =  arr.filter(function(item,index){
            if(item >=3){
              return true;
            }
      })
console.log(result);   // [3, 9]

獲取 2019-03-23格式的日期

function formatDate(dt) {
        if (!dt) {
            //若是不傳參數,則默認爲當前時間
            dt = new Date();
        }

        var year = dt.getFullYear();
        var month = dt.getMonth() + 1;
        var day = dt.getDate();

        if (month <= 10) {
            month = '0' + month;
        }

        if (day <= 10) {
            day = '0' + day;
        }

        return year + '-' + month + '-' + day;
    }

    var date = formatDate();
    console.log(date); //2019-03-23

獲取隨機數,要求長度一致的字符串格式

var random = Math.random();
    random = random + '0'.repeat(10); //repeat 重複10個0, 防止隨機數出現少於10位數的狀況
    random = random.slice(0,10)
    console.log(random); //0.70728618  每次返回的只有10位數的字符串

寫一個能遍歷對象和數組的foreach函數

function foreach(info, fn)
{
        //數組處理
        if(info instanceof Array)
        {
          info.forEach(fn)
        }else{
           //對象處理
           for( key in obj){
              fn(key, obj[key])
            }
        }
  
}

//使用方法
  var obj = {x: '我是x',y: '我是y'};
   foreach(obj, function(key,value){
    console.log(value); //我是x,我是y
  })


  var arr = [5,8,9];
  foreach(arr, function(elem,index){
    console.log(elem);//5,8,9
  })

Web_API

編寫一個通用的事件監聽函數

function bindEvent(elem,type,fn){
           elem.addEventListener( type ,fn)
 }
 //使用方法
 bindEvent(id,'click', function(e){
    console.log(e)
 })

 bindEvent(a,'click', function(e){
    e.preventDefault(); //阻止默認事件
 })

對於一個無限加載流的頁面,如何給每一個特定的標籤添加事件

//使用代理,由父級幫忙去作

 <div id="div1">
    <a href="#">a1</a>
    <a href="#">a2</a>
    <span>ddd</span>
    <a href="#">a5</a>
    <!-- 動態加載更多 -->
</div>

div1.addEventListener('click', function(e){
    if (e.target.nodeName == "A"){
        alert(e.target.innerHTML)
    }
})

完善通用綁定事件的函數,包括代理

//HTML結構
 <div id="div1">
    <a href="#">a1</a>
    <a href="#">a2</a>
    <span>ddd</span>
    <a href="#">a5</a>
    <!-- 動態加載更多 -->
</div>

<div id="div2">不使用代理</div>

//
function bindEvent(elem,type,selector, fn){
    if(fn == null){
        fn=selector;
        selector =null;
    }
    elem.addEventListener( type ,function(e){
        var target;
        if(selector){
            target = e.target;
            //matches() 方法用於檢測字符串是否匹配給定的正則表達式。
            if(target.matches(selector)){
                fn.call(target,e);
            }
        }else{
            fn.call(e);
        }
    })
}

//使用代理
bindEvent(div1,'click','a',function(e){
    console.log(this)
})
//不使用代理
bindEvent(div2,'click',function(e){
    //call改變了this指向爲e
    console.log(this.toElement.innerHTML)
})

能夠跨域的三個標籤

<img src="" alt=""> //用於打點統計
<link rel="stylesheet" href=""> //使用CDN
<script></script> // 使用JSONP

3月10日面試

閉包的優缺點

JS中,在函數外部沒法訪問函數內部的值,使用閉包就能夠作到。

  • 優勢:

    1. 使用閉包可以讓局部變量模擬全局變量同樣,可是,只能被特定函數調用。
    2. 全局變量可能會形成命名衝突,使用閉包不用擔憂這個問題,由於它是私有化,增強了封裝性。
  • 缺點

    1. 因爲閉包是駐留在內存中的,會增大內存使用量,使用不當很容易形成內存泄露,下降程序的性能。

按需引入,模塊引入的實現?

http請求緩存頭詳解

  1. Expires: http1.0 推出的,指服務器返回的文件有效期,但其實這是有缺陷的,若是把本地的時間改成2118年,那Expires的時間怎麼都會過時。
  2. Last-Modified: http1.0推出的,指服務器文件的最後修改時間,瀏覽器會帶上If-Modified-Since向服務器發送請求,與服務器文件修改時間Last-Modified作對比,若是時間不一樣,則獲取數據返回200,不然返回304後調用瀏覽器本地硬盤的緩存。
  3. Cache-Control: http1.1推出,指文件緩存的有效期。

    • .max-age:單位是s,設置文件最大緩存時間,用得最多。
    • public:緩存能夠被多用戶共享,例如360瀏覽器能夠登陸不一樣帳號,電腦系統能夠切換不一樣帳號
    • private:僅單用戶私有,不被多用戶共享
    • no-cache:不會被緩存。
    • no-store:不容許被存儲
  4. ETag: http1.1推出,該版本號是由服務端隨機生成的,瀏覽器會帶上If-None-Match向服務器發送請求,與服務器文件修改版本ETag作對比,若是版本號不一樣,則獲取數據返回200,不然返回304後調用瀏覽器本地硬盤的緩存,這種方式比Last-Modified靠譜。
相關文章
相關標籤/搜索