面試2.2

mttt發表於2018-12-11

Browser

DOM事件模型

一:DOM leave1 比如onclick只是一個屬性,可以被覆蓋,所以一個元素只能有一個onclick事件 寫在字串裡相當於執行字串裡的程式碼

在這裡插入圖片描述
在這裡插入圖片描述

二: DOM L2中,事件註冊(事件監聽佇列)

在這裡插入圖片描述
**三:**事件觸發時傳播的方式:先捕獲到最底層,再冒泡到最上層

  • 冒泡:addEventListener的第三個引數傳入 false 或者 不傳 引數 兒子,爸爸,爺爺
  • 捕獲:addEventListener的第三個引數傳入 true 爺爺,爸爸,兒子
    在這裡插入圖片描述
    冒泡和捕獲的執行順序不受程式碼順序控制。只有同一個元素的事件佇列才受於程式碼中的事件繫結順序有關
  • 阻止冒泡 event.stopPropagation()。stopPropagation,停止傳播,不要再告訴父母了,不要再往上執行冒泡事件了
  • 禁止預設效果與阻止冒泡
    
    aTag.addEventListener("click",function(e){
       e.preventDefault();//禁止預設效果
       e.stopPropagation();//阻止冒泡
    });
    
    複製程式碼

事件觸發一般來說會按照上面的順序進行,但是也有特例,如果給一個目標節點同時註冊冒泡和捕獲事件,事件觸發會按照註冊的順序執行。


// 以下會先列印冒泡然後是捕獲
node.addEventListener('click',(event) =>{
    console.log('冒泡')
},false);
node.addEventListener('click',(event) =>{
    console.log('捕獲 ')
},true)

複製程式碼

四:事件委託(事件代理) 事件代理 如果一個節點中的子節點是動態生成的,那麼子節點需要註冊事件的話應該註冊在父節點上


<ul id="ul">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
<script>
    let ul = document.querySelector('##ul')
    ul.addEventListener('click', (event) => {
        console.log(event.target);//li
        console.log(event.currentTarget)//ul
    })
</script>

複製程式碼

事件代理的方式相對於直接給目標註冊事件來說,有節省記憶體的優點 event.target和event.currentTarget的區別: event.target是點選到的最底層的那個元素 event.currentTarget是註冊事件註冊在那個元素上,那個元素就是currentTarget,所以一般是父元素

跨域

1 jsonp

什麼可以傳送請求?不光form表單可以傳送請求,a標籤(需要點選),link標籤,script,圖片,都可以傳送請求。 解決前後端耦合:前端要做的事:事先寫好成功和失敗的函式。成功了就返回給我一個成功的提示,然後我根據提示執行成功的函式,如果給我的提示是失敗,就執行失敗的函式

,不能訪問。 真名的名字應該是:動態標籤跨域請求!即利用動態標籤script進行跨域請求的技術。

面試官:說說jsonp: 為什麼要用jsonp? jsonp要解決的是瀏覽器的跨域資料訪問的問題。(兩個不同域名的網站)。 由於同源策略,不同域名不能發請求。但是HTML的<script>元素是一個例外,script標籤的請求不受域名限制的,而Ajax是受域名限制的。 如何使用jsonp?

請求方:mataotao.com的前端(瀏覽器),一個網站的前端 響應方:jack.com的後端(伺服器),另一個網站的後端 過程:

  1. 請求方動態建立一個<script>標籤。src指向響應方,同時傳一個查詢引數?callback=xxxfn
  2. 因為<script>得到響應後會立即執行響應過來的內容。所以響應方根據查詢引數構造形如xxxfn("後臺傳過來的資料")這樣的響應。把要傳的資料寫在callback函式的引數裡。
  3. 請求方瀏覽器接收到響應後, 就會執行xxxfn('後臺傳過來的資料')來得到後臺傳過來的資料,並處理。

這就是jsonp

jsonp為什麼不能用post請求 jsonp是通過動態建立script實現的,而script標籤傳送的是get請求。(缺點,get不安全) 優缺點: JSONP 使用簡單且相容性不錯,但是隻限於 get 請求

返回的狀態碼: 2開頭:成功 3開頭:重定向 4開頭:客戶端錯誤 5開頭:伺服器錯誤

Ajax

用 form 可以發get或post或其他請求,但是會重新整理頁面或新開頁面 用 a 可以發 get 請求,但是也會重新整理頁面或新開頁面 用 img 可以發 get 請求,但是隻能以圖片的形式展示 用 link 可以發 get 請求,但是隻能以 CSS、favicon 的形式展示 用 script 可以發 get 請求,但是隻能以指令碼的形式執行。 上面幾個都可以發請求,但是各有缺點。

說說Ajax: Ajax 是JS 可以用直接發起 任意HTTP 請求的技術。

  1. AJAX 通過原生的XMLHttpRequest物件發出 HTTP 請求
  2. 從伺服器獲取響應資料後,可以區域性更新當前網頁,而不用重新整理。 使用方法:

具體來說,AJAX 包括以下幾個步驟。

  • 建立 XMLHttpRequest 例項
  • 發出 HTTP 請求
  • 接收伺服器傳回的資料
  • 更新網頁資料

面試問題:請使用原生JS傳送Ajax請求 一般面試大概率會問這個問題,寫不對一定過不了面試

下面四句程式碼一定要記住:

myButton.addEventListener("click",(e)=>{
  //這四句一定要記住
  let request = new XMLHttpRequest();
  request.onreadystatechange = ()=>{
    request.onreadystatechange = ()=>{
      if(request.readyState ===4){//Ajax狀態碼為4
        console.log("請求和響應都完畢了");
        if ( request.status>=200&&request.status<300){//響應成功(http狀態碼)
          console.log(request.responseText);//列印響應的第四部分,字串
        }else if(request.status>=400){
          console.log("響應失敗");
        }
      } 
    }
  }
  request.open('GET','/xxx')//配置request.引數分別為方法和路徑
  request.setRequestHeader('content-type','x-www-form-urlencoded')//設定響應頭一定要寫在
  request.send("a=1&b=2");//傳送請求
  //這四句一定要記住
})

複製程式碼

同源策略和CORS(跨域)

什麼是同源策略?formaimglinkscript、都可以跨域傳送請求。 但是隻有 協議+域名+埠 一模一樣才允許發 AJAX 請求為什麼要有同源策略? 簡單地說就是例如使用form傳送請求後,就會重新整理頁面,所以原頁面沒有了,就認為是安全的.但是Ajax可以吧響應內容讀取了.並且顯示在本頁面上.所以出現安全性問題。

Ajax無法跨域報的錯誤:

在這裡插入圖片描述

CORS的英文Cross-Origin Resource Sharing,即跨域(源,站)資源共享(跨域) 那麼如何使用CORS突破同源策略解決Ajax的無法跨域傳送請求的問題?

只要伺服器端設定響應頭就可以實現跨域:

response.setHeader('Access-Control-Allow-Origin','http://mataotao.com:8001')
複製程式碼

這句話是CORS跨域(突破同源策略)的核心,即允許別的網站(例如http://mataotao.com:8001)跨域向我發Ajax請求,並且允許響應。

為什麼不使用jsonp,而是用CORS來跨域? CORS相對於JSONP,CORS可以發任意請求,而JSONP只能傳送get請求

JSON 和 JS 物件互轉

要實現從物件轉換為 JSON 字串,使用 JSON.stringify() 方法:

var json = JSON.stringify({a: 'Hello', b: 'World'}); //結果是 '{"a": "Hello", "b": "World"}'
複製程式碼

要實現從 JSON 轉換為物件,使用 JSON.parse() 方法:

var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //結果是 {a: 'Hello', b: 'World'}
複製程式碼

Cookie

Cookie 是伺服器儲存在瀏覽器的一小段文字資訊。瀏覽器每次向伺服器發出請求,就會自動附上這段資訊。 Cookie的作用過程:

  1. 第一次登入的時候,伺服器通過 Set-Cookie 響應頭設定 Cookie,然後以響應的形式發給瀏覽器
  2. 瀏覽器得到 響應中Cookie 之後,之後每次請求這個域名都要帶上這個 Cookie
  3. 之後伺服器讀取當時自己設定的 Cookie 就知道使用者的資訊(比如使用者名稱,是否是同一個瀏覽器等)

COokie的作用:

  1. 分辨兩個請求是否來自同一個瀏覽器
  2. 用來儲存一些狀態資訊,例如:儲存登入、購物車等需要記錄的資訊。

HTTP 回應:Cookie 的生成(伺服器端生成cookies)

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

[page content]
複製程式碼
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
複製程式碼

HTTP 請求:Cookie 的傳送(瀏覽器傳送Cookie)

瀏覽器向伺服器傳送 HTTP 請求時,每個請求都會帶上相應的 Cookie。也就是說,把伺服器早前儲存在瀏覽器的這段資訊,再發回伺服器。這時要使用 HTTP 頭資訊的Cookie欄位。

Cookie: foo=bar
複製程式碼

上面程式碼會向伺服器傳送名為foo的 Cookie,值為bar。

Cookie欄位可以包含多個 Cookie,使用分號(;)分隔。

Cookie: name=value; name2=value2; name3=value3
複製程式碼

下面是一個Http請求的例子。

GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
複製程式碼

讀、寫、刪除、Cookie

  1. document.cookie,前提是該 Cookie 不能有HTTPOnly屬性。

  2. document.cookie寫入 Cookie 的例子如下。

document.cookie = 'fontSize=14; '
  + 'expires=' + someDate.toGMTString() + '; '
  + 'path=/subdirectory; '
  + 'domain=*.example.com';
複製程式碼
  1. Cookie 的刪除 刪除一個現存 Cookie 的唯一方法,是設定它的expires屬性為一個過去的日期

session

什麼是session?

  1. 伺服器通過Cookie傳送給客戶端一個sessionID
  2. sessionID對應伺服器裡的一小塊記憶體,這裡儲存著使用者的資訊,例如登入資訊,購物車資訊等。
  3. 每次使用者訪問伺服器的時候,伺服器通過瀏覽器傳送來的cookie裡的sessionID去讀取對應的記憶體裡的資訊,以此來知道使用者的隱私資訊。

Storage

window.sessionStoragewindow.localStorage介面用於指令碼在瀏覽器儲存資料。

基本使用

設定

window.sessionStorage.setItem('key', 'value');
window.localStorage.setItem('key', 'value');
複製程式碼

獲取

window.sessionStorage.getItem('key')
window.localStorage.getItem('key')
複製程式碼

清除

localStorage.removeItem('key');
window.localStorage.clear()
複製程式碼

總結

注意只能存字串型別的。

  1. LocalStorage 跟 HTTP 無關(而cookie是http的一個頭)
  2. 傳送HTTP請求時 不會帶上 LocalStorage 的值
  3. 只有相同域名的頁面才能互相讀取 LocalStorage(沒有同源那麼嚴格)
  4. 每個域名 localStorage 最大儲存量為 5Mb 左右(每個瀏覽器不一樣)
  5. 常用場景:記錄有沒有提示過使用者(沒有用的資訊,不能記錄密碼)
  6. LocalStorage 永久有效,除非使用者主動清理快取

區別:SessionStorage 在使用者關閉頁面(會話結束)後就失效。其餘的和localstorage一樣

Cookie和Storage對比:

在這裡插入圖片描述

HTTP快取

HTTP快取有利於web效能優化。HTTP快取可以重複利用之前獲取的資源而不用反覆請求,以達到效能優化的目的。 方法

1 Cache-Control

在響應裡設定響應頭 Cache-Control: max-age=30 意思就是30秒之內,瀏覽器再訪問相同的URL的時候,就不發請求,直接從記憶體裡拿到已經快取的main.js。 問題:那麼js和css更新了怎麼辦? 瀏覽器請求時發現是相同的URL才使用快取,那麼可以設定查詢引數,例如第二個版本的js可以寫<script src="./main.js?v=2"></script>,來保證URL的不同,重新獲取新的js檔案。這樣即可以快取很久,又可以隨時更新.(總結:設定查詢引數,保證URL的不同)

Expires

  1. Expires 是以前用來控制快取的http頭,Cache-Control是新版的API。

  2. 現在首選 Cache-Control。

  3. 如果在Cache-Control響應頭設定了 "max-age" 或者 "s-max-age" 指令,那麼 Expires 頭會被忽略。

  4. 響應頭設定方式: Expires: Wed, 21 Oct 2015 07:28:00 GMT

  5. Expires 響應頭包含日期/時間, 即在此時候之後,響應過期。 注意: 因為過期標準的時間用的是本地時間,所以不靠譜,所以要遊俠使用Cache-Control代替Expires

答面試官: 與Cache-Control的區別就是:

  1. Cache-Control設定過期時間長度
  2. Expires 設定過期時間點

MD5是訊息摘要演算法。用於確保資訊傳輸完整一致。可以判斷兩次資訊傳輸是否完整一致

ETag

例如

  1. 我們請求一個js檔案。設定的ETage響應頭為這個JS檔案的MD5值
  2. 那麼,下一次請求這個JS的時候,瀏覽器會把上一次響應的那個ETage的值放到If-None-Match請求頭裡面傳送請求。
  3. 如果MD5一樣,說明檔案沒改過,那麼返回304

304 Not Modified: HTTP 304 未改變說明無需再次傳輸請求的內容,也就是說可以使用快取的內容。

HTTP 304 :沒有響應體

ETag與 Cache-Control的區別

  • 由於CSS的請求是用快取(Cache-Control)的,所以直接不發請求
  • 而js用的ETag,有請求也有響應,只不過如果MD5一樣,那麼就不下載響應體。

MVC

MVC是一種程式碼組織形式,只是組織程式碼的思想.給面試官將MVC

在這裡插入圖片描述
MVC處理的邏輯順序。

MVC就是把程式碼分為三塊

  1. V(view)只負責看得見的東西.
  2. M(model)只負責跟資料相關的操作,不會出現DOM,不會出現任何的html/css操作.例如model裡只會有初始化資料庫,獲取資料方法fetch(),儲存資料的方法save()
  3. C(controller)只負責把這些view和model組合起來,找到view,找到model,使用model完成資料修改業務,並修改view的顯示 V:檢視

M,V,C在程式碼中可以用物件或者類來表示

webpack

曾使用 webpack3 用 babel-loader 把 ES6 轉譯為 ES5 用 sass-loader 把 SCSS 轉譯為 CSS 作用:

  1. 自從出現模組化以後,檔案變多。每個 JS 檔案都要傳送請求響應,會導致載入速度變慢。Webpack 最主要的目的就是為了解決這個問題,將所有小檔案打包成一個或多個大檔案。
  2. 可以使用各種前端新技術的工具,babel,sass。

面試題彙總

前端面試題(移動適配,閉包,this,HTTP狀態嗎,排序思路,頁面載入,陣列去重)

1 請寫出一個符合 W3C 規範的 HTML 檔案

請寫出一個符合 W3C 規範的 HTML 檔案,要求

  1. 頁面標題為「我的頁面」
  2. 頁面中引入了一個外部 CSS 檔案,檔案路徑為 /style.css
  3. 頁面中引入了另一個外部 CSS 檔案,路徑為 /print.css,該檔案僅在列印時生效
  4. 頁面中引入了另一個外部 CSS 檔案,路徑為 /mobile.css,該檔案僅在裝置寬度小於 500 畫素時生效
  5. 頁面中引入了一個外部 JS 檔案,路徑為 /main.js
  6. 頁面中引入了一個外部 JS 檔案,路徑為 /gbk.js,檔案編碼為 GBK
  7. 頁面中有一個 SVG 標籤,SVG 裡面有一個直徑為 100 畫素的圓圈,顏色隨意
  8. 注意題目中的路徑
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>我的頁面</title>
    <link rel="stylesheet" href="./style.css">
    <link rel="stylesheet" href="./print.css" media="print">
    <link rel="stylesheet" href="./mobile.css" media="(max-width: 500px)">
    <style>
        body{
            padding:0;
            margin:0;
        }
    </style>
</head>
<body>
    <svg version="1.1" width="100px" height="100px" xmlns="http://www.w3.org/2000/svg">
        <circle cx="50" cy="50" r="50" fill="red"/>
    </svg>
    <script src="./main.js"></script>
    <script src="./gbk.js" charset="GBK"></script>
</body>
</html>
複製程式碼

2 移動端是怎麼做適配的?

2016年騰訊前端面試題: 移動端是怎麼做適配的? 回答要點:

  1. meta viewport
  2. 媒體查詢
  3. 動態 rem 方案

(可以參考我寫的部落格 CSS5:移動端頁面(響應式) CSS9:動態 REM-手機專用的自適應方案) 答:

2.1做手機端頁面首先要加上一個meta標籤

    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
複製程式碼

content="width=device-width表示寬度等於裝置寬度,意思就是不要將頁面寬度變成980px,用裝置寬度. user-scalable=no表示使用者不以縮放 initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0 初始縮放倍數,最大縮放倍數,最小縮放倍數,都是1.0,即不能縮放

2.2媒體查詢

通過媒體查詢,根據不同條件,使用不同的css樣式。 例如:

    <style>
        @media (max-width: 800px){/*如果媒體滿足0到800 之間,那麼會應用這裡面的樣式*/
            body{
                background-color: red;
            }
        }
    </style>
複製程式碼

2.3動態rem

因為手機需要相容很多不同寬度的手機裝置,所以將長度單位依賴於手機裝置寬度,使用動態rem方案,那麼就可以在不同手機上實現相同比例的頁面縮放而不影響佈局。 rem:root em,即<html>font-size. 實現動態rem,主要需要下面兩步: 1在<head>標籤里加上如下程式碼,讓10rem等於頁面寬度

    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
      <title>動態REM</title>
      <script>
        var pageWidth = window.innerWidth
         document.write('<style>html{font-size:'+pageWidth+'px;}</style>')
      </script>
    </head>
複製程式碼

2使用sass自動將設計稿的px轉換為rem 在scss檔案裡寫這樣一個函式:

    @function px( $px ){
    @return $px/$designWidth*10 + rem;
    }

    $designWidth : 640; // 640 是設計稿的寬度,你要根據設計稿的寬度填寫。設計師的設計稿寬度需要統一
複製程式碼

就可以使用px()函式將畫素轉化為rem。

3 實現圓角矩形和陰影怎麼做?

2017年騰訊前端實習面試題(二面): 用過CSS3嗎? 實現圓角矩形和陰影怎麼做? (搜尋MDN border-radius) 答: 用過。例如陰影,圓角,動畫,漸變和過渡 1.圓角: 簡寫屬性border-radius。例如 border-radius: 30px; border-radius: 50%; 半徑引數可以是長度單位,也可以是百分比單位。

也可以分別設定四個角

border-top-left-radius:     4px 2px;
border-top-right-radius:    3px 4px;
border-bottom-right-radius: 6px 2px;
border-bottom-left-radius:  3px 4px;
複製程式碼

半徑引數可以是一個或兩個,一個引數代表圓形圓角,兩個引數是橢圓圓角

2.陰影:

語法: box-shadow:inset x-offset y-offset blur-radius spread-radius color 五個引數分別是:投影方式 X軸偏移量 Y軸偏移量 陰影模糊半徑 陰影擴充套件半徑 陰影顏色

4 什麼是閉包,閉包的用途是什麼?

出處同上(一面二面都問了): 什麼是閉包,閉包的用途是什麼? JavaScript高程P178 閉包的用途

答:

4.1什麼是閉包

閉包是指有權訪問另一個函式作用域中的變數的函式。 例如

function foo(){
  var local = 1
  function bar(){
    local++
    return local
  }
  return bar
}

var func = foo()
func()
複製程式碼

bar函式可以訪問變數local,bar就是一個閉包。

4.2閉包的用途

  1. 模仿塊級作用域
    function A(num) {
        //核心程式碼
       (funnction(){
        for(var i = 0; i<num; i++) {
          num++;
        }
        })()
        //核心程式碼結束
        console.log(i)//underfined
      }
    複製程式碼

匿名自執行函式在內部形成了一個閉包,使i變數只有塊級作用域。閉包的本質是函式,其實在這裡閉包就是那個匿名函式,這個閉包可以得到函式A內部的活動變數,又能保證自己內部的變數在自執行後直接銷燬。

  1. 儲存變數 閉包的另一個特點是可以儲存外部函式的變數,原理是基於javascript中函式作用域鏈的特點,內部函式保留了對外部函式的活動變數的引用,所以變數不會被釋放
function B(){
   var x = 100;
   return {
       function(){
           return x
       }
   }
 }
var m = B()//執行B函式,生成活動變數 x被m引用
複製程式碼

執行B函式,生成活動變數 x被m引用, 變數x不會被銷燬。 執行B函式,返回值就是B內部的匿名函式,此時m引用了變數x,所以B執行後x不會被釋放,利用這一點,我們可以把比較重要或者計算耗費很大的值存在x中,只需要第一次計算賦值後,就可以通過m函式引用x的值,不必重複計算,同時也不容易被修改。 3. 封裝私有變數

function Person(){
   var name = 'default';
   this.getName:function(){
       return name;
   }
   this.setName:function(value){
       name = value;
   }
}
console.log(Person.getName())//default
console.log(Person.setName('mike'))
console.log(Person.getName())//mike
複製程式碼

設定了兩個閉包函式來操作Person函式內部的name變數,除了這兩個函式,在外部無法再訪問到name變數,name也就相當於是私有成員。

5 call、apply、bind 的用法分別是什麼?

阮一峰的javascript教程--this 深入淺出 妙用Javascript中apply、call、bind

答:

如果在函式中包含多層的this,this的指向是不確定的。需要把this固定下來,避免出現意想不到的情況。JavaScript提供了call、apply、bind這三個方法,來切換/固定this的指向。

5.1Function.prototype.call()

函式例項的call方法,可以指定函式內部this的指向(即函式執行時所在的作用域),然後在所指定的作用域中,呼叫該函式。

var obj = {};

var f = function () {
  return this;
};

f() === window // true
f.call(obj) === obj // true
複製程式碼

call的第一個引數就是this所要指向的那個物件,後面的引數則是函式呼叫時所需的引數。

5.2Function.prototype.apply()

apply方法的作用與call方法類似,也是改變this指向,然後再呼叫該函式。唯一的區別就是,它接收一個陣列作為函式執行時的引數。

apply方法的第一個引數也是this所要指向的那個物件,如果設為null或undefined,則等同於指定全域性物件。第二個引數則是一個陣列,該陣列的所有成員依次作為引數,傳入原函式。原函式的引數,在call方法中必須一個個新增,但是在apply方法中,必須以陣列形式新增

function f(x, y){
  console.log(x + y);
}

f.call(null, 1, 1) // 2
f.apply(null, [1, 1]) // 2
複製程式碼

5.3Function.prototype.bind()

bind方法用於將函式體內的this繫結到某個物件,然後返回一個新函式

bind方法的引數就是所要繫結this的物件。

var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};

var func = counter.inc.bind(counter);
func();
counter.count // 1
複製程式碼

上面程式碼中,counter.inc方法被賦值給變數func。這時必須用bind方法將inc內部的this,繫結到counter,否則就會出錯。

6 HTTP 狀態碼

出處同上: 請說出至少 8 個 HTTP 狀態碼,並描述各狀態碼的意義。

例如:

狀態碼 200 表示響應成功。

答:

狀態碼 202 表示:伺服器已接受請求,但尚未處理。 狀態碼 204 表示:請求處理成功,但沒有資源可返回。 狀態碼 206 表示:伺服器已經成功處理了部分 GET 請求。

狀態碼 301 表示:請求的資源已被永久的分配了新的 URI。 狀態碼 302 表示:請求的資源臨時的分配了新的 URI。

狀態碼 400 表示:請求報文中存在語法錯誤。 狀態碼 401 表示:傳送的請求需要有通過 HTTP 認證的認證資訊。 狀態碼 403 表示:對請求資源的訪問被伺服器拒絕了。 狀態碼 404 表示:伺服器上無法找到請求的資源。

狀態碼 500 表示:伺服器端在執行請求時發生了錯誤。 狀態碼 503 表示:伺服器暫時處於超負債或正在進行停機維護,現在無法處理請求。

7 寫出一個 HTTP post 請求的內容

出處同上: 請寫出一個 HTTP post 請求的內容,包括四部分。 其中 第四部分的內容是 username=ff&password=123 第二部分必須含有 Content-Type 欄位 請求的路徑為 /path

看我的部落格HTTP入門(一):在Bash中curl檢視請求與響應

答: 請求:

1 POST /path HTTP/1.1
2 Host: www.baidu.com
2 User-Agent: curl/7.20.0 (x86_64-unknown-linux-gnu) libcurl/7.20.0 zlib/1.2.8
2 Accept: */*
2 Content-Length: 24
2 Content-Type: application/x-www-form-urlencoded
3 
4 username=ff&password=123
複製程式碼

響應:

1 HTTP/1.1 200 OK
2Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
2Content-Length: 2443
2Content-Type: text/html(百度返回的時候百度的資料長度和內容的格式)
2Etag: "5886041d-98b"
2Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
3
4<!DOCTYPE html> ...
複製程式碼

1234567890

8 請說出至少三種排序的思路

這三種排序的時間複雜度分別為

O(n*n) O(n log2 n) O(n + max)

答:

O(n*n) 氣泡排序:遍歷整個陣列,依次比較相鄰兩個元素,將小的排在前面,大的排後面,這樣一遍迴圈下來就可以將最大的元素排到最後,除去已經排過的最大的數,然後再次迴圈以上操作,直到最後一個為止。

O(n log2 n) 快速排序:以第一個元素為基準,比這個元素小的元素排在左邊,比這個元素大的排右邊,再以該元素左邊和右邊的第一個元素為基準,在子區間重複以上的操作,直到只有一個數字排序為止。

O(n + max) 基數排序:首先根據個位數的數值,將需要排序的一串數值分配到0-9的桶中。接著將這些桶中的數值重新串起來,形成新的數列。接著根據十位數、百位數直至最高位重複以上操作。

9 頁面從輸入URL到頁面載入顯示完成的過程

著名前端面試題:

一個頁面從輸入 URL 到頁面載入顯示完成,這個過程中都發生了什麼? 這一題是在挖掘你的知識邊界,所以你知道多少就要答多少。

可以先查閱一些資料再查,但是不要把自己不懂的東西放在答案裡,面試官會追問的。

知乎上:從輸入 URL 到頁面載入完成的過程中都發生了什麼 答:

  1. DNS解析 DNS解析的過程就是瀏覽器查詢域名對應的 IP 地址;
  2. TCP連線 瀏覽器根據 IP 地址向伺服器發起 TCP 連線,與瀏覽器建立 TCP 三次握手: (1)主機向伺服器傳送一個建立連線的請求(您好,我想認識您); (2)伺服器接到請求後傳送同意連線的訊號(好的,很高興認識您); (3)主機接到同意連線的訊號後,再次向伺服器傳送了確認訊號(我也很高興認識您),自此,主機與伺服器兩者建立了連線。
  3. 傳送HTTP請求 瀏覽器根據 URL 內容生成 HTTP 請求報文。HTTP請求報文是由三部分組成: 請求行, 請求報頭和請求正文,其中包含請求檔案的位置、請求檔案的方式等等。
  4. 伺服器處理請求並返回HTTP報文

伺服器接到請求後,回想客戶端傳送HTTP響應報文。HTTP響應報文也是由三部分組成: 狀態碼, 響應報頭和響應報文。伺服器會根據 HTTP 請求中的內容來決定如何獲取相應的 HTML 檔案,並將得到的 HTML 檔案傳送給瀏覽器。

  1. 瀏覽器解析渲染頁面 瀏覽器是一個邊解析邊渲染的過程。在瀏覽器還沒有完全接收 HTML 檔案時便開始渲染、顯示網頁。在執行 HTML 中程式碼時,根據需要,瀏覽器會繼續請求圖片、CSS、JavsScript等檔案,過程同請求 HTML 。

  2. 關閉TCP連線或繼續保持連線

(1)主機向伺服器傳送一個斷開連線的請求(不早了,我該走了);

(2)伺服器接到請求後傳送確認收到請求的訊號(知道了);

(3)伺服器向主機傳送斷開通知(我也該走了);

(4)主機接到斷開通知後斷開連線並反饋一個確認訊號(嗯,好的),伺服器收到確認訊號後斷開連線;

10 如何實現陣列去重

著名面試題: 如何實現陣列去重? 假設有陣列 array = [1,5,2,3,4,2,3,1,3,4] 你要寫一個函式 unique,使得 unique(array) 的值為 [1,5,2,3,4] 也就是把重複的值都去掉,只保留不重複的值。

要求:

不要做多重迴圈,只能遍歷一次 請給出兩種方案,一種能在 ES 5 環境中執行,一種能在 ES 6 環境中執行(提示 ES 6 環境多了一個 Set 物件) 從 JavaScript 陣列去重談效能優化 也談JavaScript陣列去重 答:

ES5: 思路:核心是構建了一個 hash 物件來替代 indexOf. 注意在 JavaScript 裡,物件的鍵值只能是字串,因此需要 var key = typeof(item) + item 來區分數值 1 和字串 '1' 等情況。 只迴圈一遍

function unique(arr) {
  var ret = []
  var hash = {}
  for (var i = 0; i < arr.length; i++) {
    var item = arr[i]
    var key = typeof(item) + item
    if (hash[key] !== 1) {
      ret.push(item)
      hash[key] = 1
    }
  }
  return ret
}
複製程式碼

ES6:ES2015引入了一種叫作Set的資料型別。顧名思義,Set就是集合的意思,它不允許重複元素出現。 如果重複新增同一個元素的話,Set中只會存在一個。包括NaN也是這樣

function unique(array) {
   return Array.from(new Set(array));
}
複製程式碼

JS題目總結:原型鏈/new/json/MVC/Promise

1原型鏈相關

P4oVZ8.png
解讀: 上圖中,Object,Function,Array,Boolean都是構造函式

第一個框: object是例項物件,他的模板物件(原型物件)在Object()建構函式裡面. 建構函式.prototype指向的是原型物件,即模板物件. 由建構函式構造出來的例項物件.__proto__也指向的是原型物件,即模板物件. 所以true.

第二個框: fn是一個例項函式,是由用來構造出函式建構函式造出來的. 所以fn.__proto__ === Function.prototype

任何建構函式.prototype都是一個物件. 因為fn.__proto__ === Function.prototype 所以fn.__proto__.__proto__ === Object.prototype等價於 Function.prototype.__proto__ === Object.prototype 等價於 一個物件.__proto__ === Object.prototype 所以是true

第三個框同理.

第四個框比較難理解: 一個例項函式是由用來構造出函式建構函式造出來的.

Object,Function,Array都是一個例項函式,函式也是一種型別,就像String是一種型別,Number是一種型別一樣,函式這個型別裡的例項函式由函式的建構函式造出來!很難理解 所以例項函式.__proto__===建構函式.prototype 例項函式的建構函式就是Function

有點雞生蛋蛋生雞的感覺.

第五個框同理

2物件導向,new,原型鏈相關

function fn(){
    console.log(this)
}
new fn()
複製程式碼

new fn() 會執行 fn,並列印出 this,請問這個 this 有哪些屬性?這個 this 的原型有哪些屬性? 答: 這個this就是new建立的新物件. this(這個新物件)有__protot__屬性,它指向fn建構函式的原型即fn.prototype 這個原型(即fn.prototype)有兩個屬性:

  1. construct :它的值是建構函式fn
  2. __proto__: 它指向Object.prototype

解讀:

P5Ctu8.png

  1. fn()是建構函式
  2. new fn()就是一個建構函式new出來的新物件. 他的自有屬性為空,共有屬性為空,因為都沒有設定 因為他的自有屬性為空,所以他只有一個__proto__指向建構函式.prototype(即原型)了. 共有屬性為空,所以他的原型就是隻有constructor指向建構函式和__proto__指向Object.prototype(因為原型本身就是物件型別,所以指向物件的建構函式) 例子:

P5U2pd.png

P5aqUO.png

3 json

JSON 和 JavaScript 是什麼關係? JSON 和 JavaScript 的區別有哪些?

關係:JSON 是一門抄襲/借鑑 JavaScript 的語言,同時也是一種資料互動格式,JSON 是 JavaScript 的子集(或者說 JSON 只抄襲了一部分 JavaScript 語法,而且沒有新增任何原創的語法)

區別:JSON 不支援函式、undefined、變數、引用、單引號字串、物件的key不支援單引號也不支援不加引號、沒有內建的 Date、Math、RegExp 等。 而 JavaScript 全都支援。

4 MVC

前端 MVC 是什麼?(10分) 請用程式碼大概說明 MVC 三個物件分別有哪些重要屬性和方法。(10分)

答一:

MVC 是什麼 MVC 是一種設計模式(或者軟體架構),把系統分為三層:Model資料、View檢視和Controller控制器。 Model 資料管理,包括資料邏輯、資料請求、資料儲存等功能。前端 Model 主要負責 AJAX 請求或者 LocalStorage 儲存 View 負責使用者介面,前端 View 主要負責 HTML 渲染。 Controller 負責處理 View 的事件,並更新 Model;也負責監聽 Model 的變化,並更新 View,Controller 控制其他的所有流程。

答二: MVC就是把程式碼分為三塊

V(view)只負責看得見的東西. M(model)只負責跟資料相關的操作,不會出現DOM,不會出現任何的html/css操作.例如model裡只會有初始化資料庫,獲取資料方法fetch(),儲存資料的方法save() C(controller)只負責把這些view和model組合起來,找到view,找到model,使用model完成資料修改業務,並修改view的顯示 V:檢視 M:資料 C:控制器

MVC是一種程式碼組織形式,不是任何一種框架,也不是任何一種技術,只是組織程式碼的思想,要做的就是V和M傳給C,C去統籌 在js裡,MVC分別由三個物件去擔任三個職責

程式碼一:

window.View = function(xxx){
    return document.querySelector(xxx);
}
複製程式碼
window.Model = function(object){
    let resourceName = object.resourceName;
    return {
        init: function () { 
        },
        fetch: function () { 
        },
        save: function (object) {
        }
    }
}
複製程式碼
window.Controller = function(options){
    var init = options.init;
    let object = {
        view:null,
        model:null,
        init:function(view,model){
            this.view = view;
            this.model = model;
            this.model.init();
            init.call(this,view,model);
            this.bindEvents();
        },
        bindevnets:function(){},
    };

    for (let key in options) {
        if(key !=='init'){
            object[key] = options[key]
        }
    };
    return object;
}
複製程式碼

程式碼二:

var model = {
    data: null,
    init(){}
    fetch(){}
    save(){}
    update(){}
    delete(){}
}
view = {
    init() {}
    template: '<h1>hi</h1'>
}
controller = {
    view: null,
    model: null,
    init(view, model){
        this.view = view
        this.model = model
        this.bindEvents()
    }
    render(){
        this.view.querySelector('name').innerText = this.model.data.name
    },
    bindEvents(){}
}
複製程式碼

5 ES5類,原型鏈,建構函式,new

如何在 ES5 中如何用函式模擬一個類?(10分)

答一:

使用原型物件,建構函式,new來模擬類.

  1. 將公共屬性放到原型物件裡,並且將建構函式的prototype屬性指向原型物件.
  2. 私有屬性(自有屬性)放到建構函式裡去定義.
  3. 將例項化的物件的__proto__指向原型物件. 這樣當建構函式建立一個例項化的物件的時候,就即擁有自己的私有變數和方法,也有公有的變數和方法了,例項化出來的物件的私有方法和變數修改都不會互相有影響,只有在修改公有的變數和方法的時候是對所有例項生效的

答二: ES 5 沒有 class 關鍵字,所以只能使用函式來模擬類。

function Human(name){
    this.name = name
}
Human.prototype.run = function(){}

var person = new Human('frank')
複製程式碼

上面程式碼就是一個最簡單的類,Human 建構函式建立出來的物件自身有 name 屬性,其原型上面有一個 run 屬性。

Promise

用過 Promise 嗎?舉例說明。 如果要你建立一個返回 Promise 物件的函式,你會怎麼寫?舉例說明。

答:

用過Promise

答一: 用過 Promise,比如 jQuery 或者 axios 的 AJAX 功能,都返回的是 Promise 物件。

$.ajax({url:'/xxx', method:'get'}).then(success1, error1).then(success2, error2)

答二: 用過.例如使用jQuery的Ajax()傳送請求,成功或失敗後的回撥函式,就是使用promise封裝的

function success(responseText){
    console.log("成功")
    console.log(responseText);//responseTex
}
function fail(request){
    console.log("失敗")
    console.log(request);
}
myButton.addEventListener("click",(e)=>{
    //使用ajax
    $.ajax({
        method:"post",
        url:"/xxx",
        data:"username=mtt&password=1",
        dataType:'json'//預期伺服器返回的資料型別,如果不寫,就是響應裡設定的
    }
    ).then(success,fail)//$.ajax()返回一個promise
})
複製程式碼

寫Promise

function xxx(){
    return new Promise((f1, f2) => {
        doSomething()
        setTimeout(()=>{
           if(success){
               f1();
           }else{
               f2();
           }
        },3000)
    })
}


呼叫方法:
xxx().then(success, fail)
複製程式碼

或者:

function asyncMethod(){
    return new Promise(function (resolve, reject){
        setTimeout(function(){
            成功則呼叫 resolve
            失敗則呼叫 reject
        },3000)
    })
}
複製程式碼

可以看看我的部落格__使用Promise封裝Ajax

相關文章