面試2.2

Browser

DOM事件模型

一:DOM leave1 好比onclick只是一個屬性,能夠被覆蓋,因此一個元素只能有一個onclick事件 寫在字符串裏至關於運行字符串裏的代碼javascript

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

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

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

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

事件觸發通常來講會按照上面的順序進行,可是也有特例,若是給一個目標節點同時註冊冒泡和捕獲事件,事件觸發會按照註冊的順序執行。html

// 如下會先打印冒泡而後是捕獲
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,因此通常是父元素java

跨域

1 jsonp

什麼能夠發送請求?不光form表單能夠發送請求,a標籤(須要點擊),link標籤,script,圖片,均可以發送請求。 解決先後端耦合:前端要作的事:事先寫好成功和失敗的函數。成功了就返回給我一個成功的提示,而後我根據提示執行成功的函數,若是給個人提示是失敗,就執行失敗的函數node

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

面試官:說說jsonp: 爲何要用jsonp? jsonp要解決的是瀏覽器的跨域數據訪問的問題。(兩個不一樣域名的網站)。 因爲同源策略,不一樣域名不能發請求。可是HTML的<script>元素是一個例外,script標籤的請求不受域名限制的,而Ajax是受域名限制的。 如何使用jsonp?webpack

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

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

這就是jsonpgit

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

相關文章
相關標籤/搜索