史上最全的前端基礎面試題,你必須掌握哦!

FE-interview

我的收集的前端知識點、面試題和答案,參考答案僅表明我的觀點,方便複習,目錄以下,經過文檔內搜索目錄可快速定位章節javascript

$HTML, HTTP,web綜合問題

常見排序算法的時間複雜度,空間複雜度

排序算法比較

前端須要注意哪些SEO

  1. 合理的title、description、keywords:搜索對着三項的權重逐個減少,title值強調重點便可,重要關鍵詞出現不要超過2次,並且要靠前,不一樣頁面title要有所不一樣;description把頁面內容高度歸納,長度合適,不可過度堆砌關鍵詞,不一樣頁面description有所不一樣;keywords列舉出重要關鍵詞便可
  2. 語義化的HTML代碼,符合W3C規範:語義化代碼讓搜索引擎容易理解網頁
  3. 重要內容HTML代碼放在最前:搜索引擎抓取HTML順序是從上到下,有的搜索引擎對抓取長度有限制,保證重要內容必定會被抓取
  4. 重要內容不要用js輸出:爬蟲不會執行js獲取內容
  5. 少用iframe:搜索引擎不會抓取iframe中的內容
  6. 非裝飾性圖片必須加alt
  7. 提升網站速度:網站速度是搜索引擎排序的一個重要指標

web開發中會話跟蹤的方法有哪些

  1. cookie
  2. session
  3. url重寫
  4. 隱藏input
  5. ip地址

<img>titlealt有什麼區別

  1. titleglobal attributes之一,用於爲元素提供附加的advisory information。一般當鼠標滑動到元素上的時候顯示。
  2. alt<img>的特有屬性,是圖片內容的等價描述,用於圖片沒法加載時顯示、讀屏器閱讀圖片。可提圖片高可訪問性,除了純裝飾圖片外都必須設置有意義的值,搜索引擎會重點分析。

doctype是什麼,舉例常見doctype及特色

  1. <!doctype>聲明必須處於HTML文檔的頭部,在<html>標籤以前,HTML5中不區分大小寫
  2. <!doctype>聲明不是一個HTML標籤,是一個用於告訴瀏覽器當前HTMl版本的指令
  3. 現代瀏覽器的html佈局引擎經過檢查doctype決定使用兼容模式仍是標準模式對文檔進行渲染,一些瀏覽器有一個接近標準模型。
  4. 在HTML4.01中<!doctype>聲明指向一個DTD,因爲HTML4.01基於SGML,因此DTD指定了標記規則以保證瀏覽器正確渲染內容
  5. HTML5不基於SGML,因此不用指定DTD

常見dotype:css

  1. HTML4.01 strict:不容許使用表現性、廢棄元素(如font)以及frameset。聲明:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  2. HTML4.01 Transitional:容許使用表現性、廢棄元素(如font),不容許使用frameset。聲明:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  3. HTML4.01 Frameset:容許表現性元素,廢氣元素以及frameset。聲明:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
  4. XHTML1.0 Strict:不使用容許表現性、廢棄元素以及frameset。文檔必須是結構良好的XML文檔。聲明:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  5. XHTML1.0 Transitional:容許使用表現性、廢棄元素,不容許frameset,文檔必須是結構良好的XMl文檔。聲明: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  6. XHTML 1.0 Frameset:容許使用表現性、廢棄元素以及frameset,文檔必須是結構良好的XML文檔。聲明:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
  7. HTML 5: <!doctype html>

HTML全局屬性(global attribute)有哪些

參考資料:MDN: html global attribute或者W3C HTML global-attributeshtml

  • accesskey:設置快捷鍵,提供快速訪問元素如aaa在windows下的firefox中按alt + shift + a可激活元素
  • class:爲元素設置類標識,多個類名用空格分開,CSS和javascript可經過class屬性獲取元素
  • contenteditable: 指定元素內容是否可編輯
  • contextmenu: 自定義鼠標右鍵彈出菜單內容
  • data-*: 爲元素增長自定義屬性
  • dir: 設置元素文本方向
  • draggable: 設置元素是否可拖拽
  • dropzone: 設置元素拖放類型: copy, move, link
  • hidden: 表示一個元素是否與文檔。樣式上會致使元素不顯示,可是不能用這個屬性實現樣式效果
  • id: 元素id,文檔內惟一
  • lang: 元素內容的的語言
  • spellcheck: 是否啓動拼寫和語法檢查
  • style: 行內css樣式
  • tabindex: 設置元素能夠得到焦點,經過tab能夠導航
  • title: 元素相關的建議信息
  • translate: 元素和子孫節點內容是否須要本地化

什麼是web語義化,有什麼好處

web語義化是指經過HTML標記表示頁面包含的信息,包含了HTML標籤的語義化和css命名的語義化。 HTML標籤的語義化是指:經過使用包含語義的標籤(如h1-h6)恰當地表示文檔結構 css命名的語義化是指:爲html標籤添加有意義的class,id補充未表達的語義,如Microformat經過添加符合規則的class描述信息 爲何須要語義化:前端

  • 去掉樣式後頁面呈現清晰的結構
  • 盲人使用讀屏器更好地閱讀
  • 搜索引擎更好地理解頁面,有利於收錄
  • 便團隊項目的可持續運做及維護

HTTP method

  1. 一臺服務器要與HTTP1.1兼容,只要爲資源實現GETHEAD方法便可
  2. GET是最經常使用的方法,一般用於請求服務器發送某個資源
  3. HEAD與GET相似,但服務器在響應中值返回首部,不返回實體的主體部分
  4. PUT讓服務器用請求的主體部分來建立一個由所請求的URL命名的新文檔,或者,若是那個URL已經存在的話,就用幹這個主體替代它
  5. POST起初是用來向服務器輸入數據的。實際上,一般會用它來支持HTML的表單。表單中填好的數據一般會被送給服務器,而後由服務器將其發送到要去的地方。
  6. TRACE會在目的服務器端發起一個環回診斷,最後一站的服務器會彈回一個TRACE響應並在響應主體中攜帶它收到的原始請求報文。TRACE方法主要用於診斷,用於驗證請求是否如願穿過了請求/響應鏈。
  7. OPTIONS方法請求web服務器告知其支持的各類功能。能夠查詢服務器支持哪些方法或者對某些特殊資源支持哪些方法。
  8. DELETE請求服務器刪除請求URL指定的資源

從瀏覽器地址欄輸入url到顯示頁面的步驟(以HTTP爲例)

  1. 在瀏覽器地址欄輸入URL
  2. 瀏覽器查看緩存,若是請求資源在緩存中而且新鮮,跳轉到轉碼步驟
    1. 若是資源未緩存,發起新請求
    2. 若是已緩存,檢驗是否足夠新鮮,足夠新鮮直接提供給客戶端,不然與服務器進行驗證。
    3. 檢驗新鮮一般有兩個HTTP頭進行控制ExpiresCache-Control
      • HTTP1.0提供Expires,值爲一個絕對時間表示緩存新鮮日期
      • HTTP1.1增長了Cache-Control: max-age=,值爲以秒爲單位的最大新鮮時間
  3. 瀏覽器解析URL獲取協議,主機,端口,path
  4. 瀏覽器組裝一個HTTP(GET)請求報文
  5. 瀏覽器獲取主機ip地址,過程以下:
    1. 瀏覽器緩存
    2. 本機緩存
    3. hosts文件
    4. 路由器緩存
    5. ISP DNS緩存
    6. DNS遞歸查詢(可能存在負載均衡致使每次IP不同)
  6. 打開一個socket與目標IP地址,端口創建TCP連接,三次握手以下:
    1. 客戶端發送一個TCP的SYN=1,Seq=X的包到服務器端口
    2. 服務器發回SYN=1, ACK=X+1, Seq=Y的響應包
    3. 客戶端發送ACK=Y+1, Seq=Z
  7. TCP連接創建後發送HTTP請求
  8. 服務器接受請求並解析,將請求轉發到服務程序,如虛擬主機使用HTTP Host頭部判斷請求的服務程序
  9. 服務器檢查HTTP請求頭是否包含緩存驗證信息若是驗證緩存新鮮,返回304等對應狀態碼
  10. 處理程序讀取完整請求並準備HTTP響應,可能須要查詢數據庫等操做
  11. 服務器將響應報文經過TCP鏈接發送回瀏覽器
  12. 瀏覽器接收HTTP響應,而後根據狀況選擇關閉TCP鏈接或者保留重用,關閉TCP鏈接的四次握手以下
    1. 主動方發送Fin=1, Ack=Z, Seq= X報文
    2. 被動方發送ACK=X+1, Seq=Z報文
    3. 被動方發送Fin=1, ACK=X, Seq=Y報文
    4. 主動方發送ACK=Y, Seq=X報文
  13. 瀏覽器檢查響應狀態嗎:是否爲1XX,3XX, 4XX, 5XX,這些狀況處理與2XX不一樣
  14. 若是資源可緩存,進行緩存
  15. 對響應進行解碼(例如gzip壓縮)
  16. 根據資源類型決定如何處理(假設資源爲HTML文檔)
  17. 解析HTML文檔,構件DOM樹,下載資源,構造CSSOM樹,執行js腳本,這些操做沒有嚴格的前後順序,如下分別解釋
  18. 構建DOM樹
    1. Tokenizing:根據HTML規範將字符流解析爲標記
    2. Lexing:詞法分析將標記轉換爲對象並定義屬性和規則
    3. DOM construction:根據HTML標記關係將對象組成DOM樹
  19. 解析過程當中遇到圖片、樣式表、js文件,啓動下載
  20. 構建CSSOM樹
    1. Tokenizing:字符流轉換爲標記流
    2. Node:根據標記建立節點
    3. CSSOM:節點建立CSSOM樹
  21. 根據DOM樹和CSSOM樹構建渲染樹:
    1. 從DOM樹的根節點遍歷全部可見節點,不可見節點包括:1)script,meta這樣自己不可見的標籤。2)被css隱藏的節點,如display: none
    2. 對每個可見節點,找到恰當的CSSOM規則並應用
    3. 發佈可視節點的內容和計算樣式
  22. js解析以下
    1. 瀏覽器建立Document對象並解析HTML,將解析到的元素和文本節點添加到文檔中,此時document.readystate爲loading
    2. HTML解析器遇到沒有async和defer的script時,將他們添加到文檔中,而後執行行內或外部腳本。這些腳本會同步執行,而且在腳本下載和執行時解析器會暫停。這樣就能夠用document.write()把文本插入到輸入流中。同步腳本常常簡單定義函數和註冊事件處理程序,他們能夠遍歷和操做script和他們以前的文檔內容
    3. 當解析器遇到設置了async屬性的script時,開始下載腳本並繼續解析文檔。腳本會在它下載完成後儘快執行,可是解析器不會停下來等它下載。異步腳本禁止使用document.write(),它們能夠訪問本身script和以前的文檔元素
    4. 當文檔完成解析,document.readState變成interactive
    5. 全部defer腳本會按照在文檔出現的順序執行,延遲腳本能訪問完整文檔樹,禁止使用document.write()
    6. 瀏覽器在Document對象上觸發DOMContentLoaded事件
    7. 此時文檔徹底解析完成,瀏覽器可能還在等待如圖片等內容加載,等這些內容完成載入而且全部異步腳本完成載入和執行,document.readState變爲complete,window觸發load事件
  23. 顯示頁面(HTML解析過程當中會逐步顯示頁面)

HTTP request報文結構是怎樣的

rfc2616中進行了定義:java

  1. 首行是Request-Line包括:請求方法請求URI協議版本CRLF
  2. 首行以後是若干行請求頭,包括general-headerrequest-header或者entity-header,每一個一行以CRLF結束
  3. 請求頭和消息實體之間有一個CRLF分隔
  4. 根據實際請求須要可能包含一個消息實體 一個請求報文例子以下:
GET /Protocols/rfc2616/rfc2616-sec5.html HTTP/1.1
Host: www.w3.org
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
Referer: https://www.google.com.hk/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: authorstyle=yes
If-None-Match: "2cc8-3e3073913b100"
If-Modified-Since: Wed, 01 Sep 2004 13:24:52 GMT

name=qiu&age=25
複製代碼

HTTP response報文結構是怎樣的

rfc2616中進行了定義:node

  1. 首行是狀態行包括:HTTP版本,狀態碼,狀態描述,後面跟一個CRLF
  2. 首行以後是若干行響應頭,包括:通用頭部,響應頭部,實體頭部
  3. 響應頭部和響應實體之間用一個CRLF空行分隔
  4. 最後是一個可能的消息實體 響應報文例子以下:
HTTP/1.1 200 OK
Date: Tue, 08 Jul 2014 05:28:43 GMT
Server: Apache/2
Last-Modified: Wed, 01 Sep 2004 13:24:52 GMT
ETag: "40d7-3e3073913b100"
Accept-Ranges: bytes
Content-Length: 16599
Cache-Control: max-age=21600
Expires: Tue, 08 Jul 2014 11:28:43 GMT
P3P: policyref="http://www.w3.org/2001/05/P3P/p3p.xml"
Content-Type: text/html; charset=iso-8859-1

{"name": "qiu", "age": 25}
複製代碼

如何進行網站性能優化

雅虎Best Practices for Speeding Up Your Web Sitejquery

  • content方面git

    1. 減小HTTP請求:合併文件、CSS精靈、inline Image
    2. 減小DNS查詢:DNS查詢完成以前瀏覽器不能從這個主機下載任何任何文件。方法:DNS緩存、將資源分佈到恰當數量的主機名,平衡並行下載和DNS查詢
    3. 避免重定向:多餘的中間訪問
    4. 使Ajax可緩存
    5. 非必須組件延遲加載
    6. 將來所需組件預加載
    7. 減小DOM元素數量
    8. 將資源放到不一樣的域下:瀏覽器同時從一個域下載資源的數目有限,增長域能夠提升並行下載量
    9. 減小iframe數量
    10. 不要404
  • Server方面github

    1. 使用CDN
    2. 添加Expires或者Cache-Control響應頭
    3. 對組件使用Gzip壓縮
    4. 配置ETag
    5. Flush Buffer Early
    6. Ajax使用GET進行請求
    7. 避免空src的img標籤
  • Cookie方面web

    1. 減少cookie大小
    2. 引入資源的域名不要包含cookie
  • css方面

    1. 將樣式表放到頁面頂部
    2. 不使用CSS表達式
    3. 使用不使用@import
    4. 不使用IE的Filter
  • Javascript方面

    1. 將腳本放到頁面底部
    2. 將javascript和css從外部引入
    3. 壓縮javascript和css
    4. 刪除不須要的腳本
    5. 減小DOM訪問
    6. 合理設計事件監聽器
  • 圖片方面

    1. 優化圖片:根據實際顏色須要選擇色深、壓縮
    2. 優化css精靈
    3. 不要在HTML中拉伸圖片
    4. 保證favicon.ico小而且可緩存
  • 移動方面

    1. 保證組件小於25k
    2. Pack Components into a Multipart Document

什麼是漸進加強

漸進加強是指在web設計時強調可訪問性、語義化HTML標籤、外部樣式表和腳本。保證全部人都能訪問頁面的基本內容和功能同時爲高級瀏覽器和高帶寬用戶提供更好的用戶體驗。核心原則以下:

  • 全部瀏覽器都必須能訪問基本內容
  • 全部瀏覽器都必須能使用基本功能
  • 全部內容都包含在語義化標籤中
  • 經過外部CSS提供加強的佈局
  • 經過非侵入式、外部javascript提供加強功能
  • end-user web browser preferences are respected

HTTP狀態碼及其含義

參考RFC 2616

  • 1XX:信息狀態碼
    • 100 Continue:客戶端應當繼續發送請求。這個臨時相應是用來通知客戶端它的部分請求已經被服務器接收,且仍未被拒絕。客戶端應當繼續發送請求的剩餘部分,或者若是請求已經完成,忽略這個響應。服務器必須在請求萬仇向客戶端發送一個最終響應
    • 101 Switching Protocols:服務器已經理解力客戶端的請求,並將經過Upgrade消息頭通知客戶端採用不一樣的協議來完成這個請求。在發送完這個響應最後的空行後,服務器將會切換到Upgrade消息頭中定義的那些協議。
  • 2XX:成功狀態碼
    • 200 OK:請求成功,請求所但願的響應頭或數據體將隨此響應返回
    • 201 Created
    • 202 Accepted
    • 203 Non-Authoritative Information
    • 204 No Content
    • 205 Reset Content
    • 206 Partial Content
  • 3XX:重定向
    • 300 Multiple Choices
    • 301 Moved Permanently
    • 302 Found
    • 303 See Other
    • 304 Not Modified
    • 305 Use Proxy
    • 306 (unused)
    • 307 Temporary Redirect
  • 4XX:客戶端錯誤
    • 400 Bad Request:
    • 401 Unauthorized:
    • 402 Payment Required:
    • 403 Forbidden:
    • 404 Not Found:
    • 405 Method Not Allowed:
    • 406 Not Acceptable:
    • 407 Proxy Authentication Required:
    • 408 Request Timeout:
    • 409 Conflict:
    • 410 Gone:
    • 411 Length Required:
    • 412 Precondition Failed:
    • 413 Request Entity Too Large:
    • 414 Request-URI Too Long:
    • 415 Unsupported Media Type:
    • 416 Requested Range Not Satisfiable:
    • 417 Expectation Failed:
  • 5XX: 服務器錯誤
    • 500 Internal Server Error:
    • 501 Not Implemented:
    • 502 Bad Gateway:
    • 503 Service Unavailable:
    • 504 Gateway Timeout:
    • 505 HTTP Version Not Supported:

$CSS部分

CSS選擇器有哪些

  1. *通用選擇器:選擇全部元素,不參與計算優先級,兼容性IE6+
  2. #X id選擇器:選擇id值爲X的元素,兼容性:IE6+
  3. .X 類選擇器: 選擇class包含X的元素,兼容性:IE6+
  4. X Y後代選擇器: 選擇知足X選擇器的後代節點中知足Y選擇器的元素,兼容性:IE6+
  5. X 元素選擇器: 選擇標全部籤爲X的元素,兼容性:IE6+
  6. :link,:visited,:focus,:hover,:active連接狀態: 選擇特定狀態的連接元素,順序LoVe HAte,兼容性: IE4+
  7. X + Y直接兄弟選擇器:在X以後第一個兄弟節點中選擇知足Y選擇器的元素,兼容性: IE7+
  8. X > Y子選擇器: 選擇X的子元素中知足Y選擇器的元素,兼容性: IE7+
  9. X ~ Y兄弟: 選擇X以後全部兄弟節點中知足Y選擇器的元素,兼容性: IE7+
  10. [attr]:選擇全部設置了attr屬性的元素,兼容性IE7+
  11. [attr=value]:選擇屬性值恰好爲value的元素
  12. [attr~=value]:選擇屬性值爲空白符分隔,其中一個的值恰好是value的元素
  13. [attr|=value]:選擇屬性值恰好爲value或者value-開頭的元素
  14. [attr^=value]:選擇屬性值以value開頭的元素
  15. [attr$=value]:選擇屬性值以value結尾的元素
  16. [attr=value]*:選擇屬性值中包含value的元素
  17. [:checked]:選擇單選框,複選框,下拉框中選中狀態下的元素,兼容性:IE9+
  18. X:after, X::after:after僞元素,選擇元素虛擬子元素(元素的最後一個子元素),CSS3中::表示僞元素。兼容性:after爲IE8+,::after爲IE9+
  19. :hover:鼠標移入狀態的元素,兼容性a標籤IE4+, 全部元素IE7+
  20. :not(selector):選擇不符合selector的元素。不參與計算優先級,兼容性:IE9+
  21. ::first-letter:僞元素,選擇塊元素第一行的第一個字母,兼容性IE5.5+
  22. ::first-line:僞元素,選擇塊元素的第一行,兼容性IE5.5+
  23. :nth-child(an + b):僞類,選擇前面有an + b - 1個兄弟節點的元素,其中n >= 0, 兼容性IE9+
  24. :nth-last-child(an + b):僞類,選擇後面有an + b - 1個兄弟節點的元素 其中n >= 0,兼容性IE9+
  25. X:nth-of-type(an+b):僞類,X爲選擇器,解析獲得元素標籤,選擇前面有an + b - 1個相同標籤兄弟節點的元素。兼容性IE9+
  26. X:nth-last-of-type(an+b):僞類,X爲選擇器,解析獲得元素標籤,選擇後面有an+b-1個相同標籤兄弟節點的元素。兼容性IE9+
  27. X:first-child:僞類,選擇知足X選擇器的元素,且這個元素是其父節點的第一個子元素。兼容性IE7+
  28. X:last-child:僞類,選擇知足X選擇器的元素,且這個元素是其父節點的最後一個子元素。兼容性IE9+
  29. X:only-child:僞類,選擇知足X選擇器的元素,且這個元素是其父元素的惟一子元素。兼容性IE9+
  30. X:only-of-type:僞類,選擇X選擇的元素,解析獲得元素標籤,若是該元素沒有相同類型的兄弟節點時選中它。兼容性IE9+
  31. X:first-of-type:僞類,選擇X選擇的元素,解析獲得元素標籤,若是該元素 是此此類型元素的第一個兄弟。選中它。兼容性IE9+

css sprite是什麼,有什麼優缺點

概念:將多個小圖片拼接到一個圖片中。經過background-position和元素尺寸調節須要顯示的背景圖案。

優勢:

  1. 減小HTTP請求數,極大地提升頁面加載速度
  2. 增長圖片信息重複度,提升壓縮比,減小圖片大小
  3. 更換風格方便,只需在一張或幾張圖片上修改顏色或樣式便可實現

缺點:

  1. 圖片合併麻煩
  2. 維護麻煩,修改一個圖片可能須要重新佈局整個圖片,樣式

display: none;visibility: hidden;的區別

聯繫:它們都能讓元素不可見

區別:

  1. display:none;會讓元素徹底從渲染樹中消失,渲染的時候不佔據任何空間;visibility: hidden;不會讓元素從渲染樹消失,渲染師元素繼續佔據空間,只是內容不可見
  2. display: none;是非繼承屬性,子孫節點消失因爲元素從渲染樹消失形成,經過修改子孫節點屬性沒法顯示;visibility: hidden;是繼承屬性,子孫節點消失因爲繼承了hidden,經過設置visibility: visible;可讓子孫節點顯式
  3. 修改常規流中元素的display一般會形成文檔重排。修改visibility屬性只會形成本元素的重繪。
  4. 讀屏器不會讀取display: none;元素內容;會讀取visibility: hidden;元素內容

css hack原理及經常使用hack

原理:利用不一樣瀏覽器對CSS的支持和解析結果不同編寫針對特定瀏覽器樣式。常見的hack有1)屬性hack。2)選擇器hack。3)IE條件註釋

  • IE條件註釋:適用於[IE5, IE9]常見格式以下
<!--[if IE 6]>
Special instructions for IE 6 here
<![endif]-->
複製代碼
  • 選擇器hack:不一樣瀏覽器對選擇器的支持不同
/***** Selector Hacks ******/

/* IE6 and below */
* html #uno { color: red }

/* IE7 */
*:first-child+html #dos { color: red }

/* IE7, FF, Saf, Opera  */
html>body #tres { color: red }

/* IE8, FF, Saf, Opera (Everything but IE 6,7) */
html>/**/body #cuatro { color: red }

/* Opera 9.27 and below, safari 2 */
html:first-child #cinco { color: red }

/* Safari 2-3 */
html[xmlns*=""] body:last-child #seis { color: red }

/* safari 3+, chrome 1+, opera9+, ff 3.5+ */
body:nth-of-type(1) #siete { color: red }

/* safari 3+, chrome 1+, opera9+, ff 3.5+ */
body:first-of-type #ocho { color: red }

/* saf3+, chrome1+ */
@media screen and (-webkit-min-device-pixel-ratio:0) {
 #diez { color: red }
}

/* iPhone / mobile webkit */
@media screen and (max-device-width: 480px) {
 #veintiseis { color: red }
}

/* Safari 2 - 3.1 */
html[xmlns*=""]:root #trece { color: red }

/* Safari 2 - 3.1, Opera 9.25 */
*|html[xmlns*=""] #catorce { color: red }

/* Everything but IE6-8 */
:root *> #quince { color: red }

/* IE7 */
*+html #dieciocho { color: red }

/* Firefox only. 1+ */
#veinticuatro, x:-moz-any-link { color: red }

/* Firefox 3.0+ */
#veinticinco, x:-moz-any-link, x:default { color: red }
複製代碼
  • 屬性hack:不一樣瀏覽器解析bug或方法
/* IE6 */
#once { _color: blue }

/* IE6, IE7 */
#doce { *color: blue; /* or #color: blue */ }

/* Everything but IE6 */
#diecisiete { color/**/: blue }

/* IE6, IE7, IE8 */
#diecinueve { color: blue\9; }

/* IE7, IE8 */
#veinte { color/*\**/: blue\9; }

/* IE6, IE7 -- acts as an !important */
#veintesiete { color: blue !ie; } /* string after ! can be anything */
複製代碼

specified value,computed value,used value計算方法

  • specified value: 計算方法以下:

    1. 若是樣式表設置了一個值,使用這個值
    2. 若是沒有設置值,這個屬性是繼承屬性,從父元素繼承
    3. 若是沒設置,而且不是繼承屬性,使用css規範指定的初始值
  • computed value: 以specified value根據規範定義的行爲進行計算,一般將相對值計算爲絕對值,例如em根據font-size進行計算。一些使用百分數而且須要佈局來決定最終值的屬性,如width,margin。百分數就直接做爲computed value。line-height的無單位值也直接做爲computed value。這些值將在計算used value時獲得絕對值。computed value的主要做用是用於繼承

  • used value:屬性計算後的最終值,對於大多數屬性能夠經過window.getComputedStyle得到,尺寸值單位爲像素。如下屬性依賴於佈局,

    • background-position
    • bottom, left, right, top
    • height, width
    • margin-bottom, margin-left, margin-right, margin-top
    • min-height, min-width
    • padding-bottom, padding-left, padding-right, padding-top
    • text-indent

link@import的區別

  1. link是HTML方式, @import是CSS方式
  2. link最大限度支持並行下載,@import過多嵌套致使串行下載,出現FOUC
  3. link能夠經過rel="alternate stylesheet"指定候選樣式
  4. 瀏覽器對link支持早於@import,可使用@import對老瀏覽器隱藏樣式
  5. @import必須在樣式規則以前,能夠在css文件中引用其餘文件
  6. 整體來講:link優於@import

display: block;display: inline;的區別

block元素特色:

1.處於常規流中時,若是width沒有設置,會自動填充滿父容器 2.能夠應用margin/padding 3.在沒有設置高度的狀況下會擴展高度以包含常規流中的子元素 4.處於常規流中時佈局時在先後元素位置之間(獨佔一個水平空間) 5.忽略vertical-align

inline元素特色

1.水平方向上根據direction依次佈局 2.不會在元素先後進行換行 3.受white-space控制 4.margin/padding在豎直方向上無效,水平方向上有效 5.width/height屬性對非替換行內元素無效,寬度由元素內容決定 6.非替換行內元素的行框高由line-height肯定,替換行內元素的行框高由height,margin,padding,border決定 6.浮動或絕對定位時會轉換爲block 7.vertical-align屬性生效

PNG,GIF,JPG的區別及如何選

參考資料: 選擇正確的圖片格式 GIF:

  1. 8位像素,256色
  2. 無損壓縮
  3. 支持簡單動畫
  4. 支持boolean透明
  5. 適合簡單動畫

JPEG

  1. 顏色限於256
  2. 有損壓縮
  3. 可控制壓縮質量
  4. 不支持透明
  5. 適合照片

PNG

  1. 有PNG8和truecolor PNG
  2. PNG8相似GIF顏色上限爲256,文件小,支持alpha透明度,無動畫
  3. 適合圖標、背景、按鈕

CSS有哪些繼承屬性

IE6瀏覽器有哪些常見的bug,缺陷或者與標準不一致的地方,如何解決

  • IE6不支持min-height,解決辦法使用css hack:
.target {
    min-height: 100px;
    height: auto !important;
    height: 100px;   // IE6下內容高度超過會自動擴展高度
}
複製代碼
  • olli的序號全爲1,不遞增。解決方法:爲li設置樣式display: list-item;

  • 未定位父元素overflow: auto;,包含position: relative;子元素,子元素高於父元素時會溢出。解決辦法:1)子元素去掉position: relative;; 2)不能爲子元素去掉定位時,父元素position: relative;

<style type="text/css">
.outer {
    width: 215px;
    height: 100px;
    border: 1px solid red;
    overflow: auto;
    position: relative;  /* 修復bug */
}
.inner {
    width: 100px;
    height: 200px;
    background-color: purple;
    position: relative;
}
</style>

<div class="outer">
    <div class="inner"></div>
</div>
複製代碼
  • IE6只支持a標籤的:hover僞類,解決方法:使用js爲元素監聽mouseenter,mouseleave事件,添加類實現效果:
<style type="text/css">
.p:hover,
.hover {
    background: purple;
}
</style>

<p class="p" id="target">aaaa bbbbb<span>DDDDDDDDDDDd</span> aaaa lkjlkjdf j</p>

<script type="text/javascript">
function addClass(elem, cls) {
    if (elem.className) {
        elem.className += ' ' + cls;
    } else {
        elem.className = cls;
    }
}
function removeClass(elem, cls) {
    var className = ' ' + elem.className + ' ';
    var reg = new RegExp(' +' + cls + ' +', 'g');
    elem.className = className.replace(reg, ' ').replace(/^ +| +$/, '');
}

var target = document.getElementById('target');
if (target.attachEvent) {
    target.attachEvent('onmouseenter', function () {
        addClass(target, 'hover');
    });
    target.attachEvent('onmouseleave', function () {
        removeClass(target, 'hover');
    })
}
</script>
複製代碼
  • IE5-8不支持opacity,解決辦法:
.opacity {
    opacity: 0.4
    filter: alpha(opacity=60); /* for IE5-7 */
    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; /* for IE 8*/
}
複製代碼
  • IE6在設置height小於font-size時高度值爲font-size,解決辦法:font-size: 0;
  • IE6不支持PNG透明背景,解決辦法: IE6下使用gif圖片
  • IE6-7不支持display: inline-block解決辦法:設置inline並觸發hasLayout
display: inline-block;
    *display: inline;
    *zoom: 1;
複製代碼
  • IE6下浮動元素在浮動方向上與父元素邊界接觸元素的外邊距會加倍。解決辦法: 1)使用padding控制間距。 2)浮動元素display: inline;這樣解決問題且無任何反作用:css標準規定浮動元素display:inline會自動調整爲block
  • 經過爲塊級元素設置寬度和左右margin爲auto時,IE6不能實現水平居中,解決方法:爲父元素設置text-align: center;

容器包含若干浮動元素時如何清理(包含)浮動

  1. 容器元素閉合標籤前添加額外元素並設置clear: both
  2. 父元素觸發塊級格式化上下文(見塊級可視化上下文部分)
  3. 設置容器元素僞元素進行清理推薦的清理浮動方法
/**
* 在標準瀏覽器下使用
* 1 content內容爲空格用於修復opera下文檔中出現
*   contenteditable屬性時在清理浮動元素上下的空白
* 2 使用display使用table而不是block:能夠防止容器和
*   子元素top-margin摺疊,這樣能使清理效果與BFC,IE6/7
*   zoom: 1;一致
**/

.clearfix:before,
.clearfix:after {
    content: " "; /* 1 */
    display: table; /* 2 */
}

.clearfix:after {
    clear: both;
}

/**
* IE 6/7下使用
* 經過觸發hasLayout實現包含浮動
**/
.clearfix {
    *zoom: 1;
}
複製代碼

什麼是FOUC?如何避免

Flash Of Unstyled Content:用戶定義樣式表加載以前瀏覽器使用默認樣式顯示文檔,用戶樣式加載渲染以後再重新顯示文檔,形成頁面閃爍。解決方法:把樣式表放到文檔的head

如何建立塊級格式化上下文(block formatting context),BFC有什麼用

建立規則:

  1. 根元素
  2. 浮動元素(float不是none
  3. 絕對定位元素(position取值爲absolutefixed
  4. display取值爲inline-block,table-cell, table-caption,flex, inline-flex之一的元素
  5. overflow不是visible的元素

做用:

  1. 能夠包含浮動元素
  2. 不被浮動元素覆蓋
  3. 阻止父子元素的margin摺疊

display,float,position的關係

  1. 若是display爲none,那麼position和float都不起做用,這種狀況下元素不產生框
  2. 不然,若是position值爲absolute或者fixed,框就是絕對定位的,float的計算值爲none,display根據下面的表格進行調整。
  3. 不然,若是float不是none,框是浮動的,display根據下表進行調整
  4. 不然,若是元素是根元素,display根據下表進行調整
  5. 其餘狀況下display的值爲指定值 總結起來:絕對定位、浮動、根元素都須要調整display
    display轉換規則

外邊距摺疊(collapsing margins)

毗鄰的兩個或多個margin會合併成一個margin,叫作外邊距摺疊。規則以下:

  1. 兩個或多個毗鄰的普通流中的塊元素垂直方向上的margin會摺疊
  2. 浮動元素/inline-block元素/絕對定位元素的margin不會和垂直方向上的其餘元素的margin摺疊
  3. 建立了塊級格式化上下文的元素,不會和它的子元素髮生margin摺疊
  4. 元素自身的margin-bottom和margin-top相鄰時也會摺疊

如何肯定一個元素的包含塊(containing block)

  1. 根元素的包含塊叫作初始包含塊,在連續媒體中他的尺寸與viewport相同而且anchored at the canvas origin;對於paged media,它的尺寸等於page area。初始包含塊的direction屬性與根元素相同。

  2. positionrelative或者static的元素,它的包含塊由最近的塊級(displayblock,list-item, table)祖先元素的內容框組成

  3. 若是元素positionfixed。對於連續媒體,它的包含塊爲viewport;對於paged media,包含塊爲page area

  4. 若是元素positionabsolute,它的包含塊由祖先元素中最近一個positionrelative,absolute或者fixed的元素產生,規則以下:

    • 若是祖先元素爲行內元素,the containing block is the bounding box around the padding boxes of the first and the last inline boxes generated for that element.
    • 其餘狀況下包含塊由祖先節點的padding edge組成

    若是找不到定位的祖先元素,包含塊爲初始包含塊

stacking context,佈局規則

z軸上的默認層疊順序以下(從下到上):

  1. 根元素的邊界和背景
  2. 常規流中的元素按照html中順序
  3. 浮動塊
  4. positioned元素按照html中出現順序

如何建立stacking context:

  1. 根元素
  2. z-index不爲auto的定位元素
  3. a flex item with a z-index value other than 'auto'
  4. opacity小於1的元素
  5. 在移動端webkit和chrome22+,z-index爲auto,position: fixed也將建立新的stacking context

如何水平居中一個元素

  • 若是須要居中的元素爲常規流中inline元素,爲父元素設置text-align: center;便可實現
  • 若是須要居中的元素爲常規流中block元素,1)爲元素設置寬度,2)設置左右margin爲auto。3)IE6下需在父元素上設置text-align: center;,再給子元素恢復須要的值
<body>
    <div class="content">
    aaaaaa aaaaaa a a a a a a a a
    </div>
</body>

<style>
    body {
        background: #DDD;
        text-align: center; /* 3 */
    }
    .content {
        width: 500px;      /* 1 */
        text-align: left;  /* 3 */
        margin: 0 auto;    /* 2 */

        background: purple;
    }
</style>
複製代碼
  • 若是須要居中的元素爲浮動元素,1)爲元素設置寬度,2)position: relative;,3)浮動方向偏移量(left或者right)設置爲50%,4)浮動方向上的margin設置爲元素寬度一半乘以-1
<body>
    <div class="content">
    aaaaaa aaaaaa a a a a a a a a
    </div>
</body>

<style>
    body {
        background: #DDD;
    }
    .content {
        width: 500px;         /* 1 */
        float: left;

        position: relative;   /* 2 */
        left: 50%;            /* 3 */
        margin-left: -250px;  /* 4 */

        background-color: purple;
    }
</style>
複製代碼
  • 若是須要居中的元素爲絕對定位元素,1)爲元素設置寬度,2)偏移量設置爲50%,3)偏移方向外邊距設置爲元素寬度一半乘以-1
<body>
    <div class="content">
    aaaaaa aaaaaa a a a a a a a a
    </div>
</body>

<style>
    body {
        background: #DDD;
        position: relative;
    }
    .content {
        width: 800px;

        position: absolute;
        left: 50%;
        margin-left: -400px;

        background-color: purple;
    }
</style>
複製代碼
  • 若是須要居中的元素爲絕對定位元素,1)爲元素設置寬度,2)設置左右偏移量都爲0,3)設置左右外邊距都爲auto
<body>
    <div class="content">
    aaaaaa aaaaaa a a a a a a a a
    </div>
</body>

<style>
    body {
        background: #DDD;
        position: relative;
    }
    .content {
        width: 800px;

        position: absolute;
        margin: 0 auto;
        left: 0;
        right: 0;

        background-color: purple;
    }
</style>
複製代碼

如何豎直居中一個元素

參考資料:6 Methods For Vertical Centering With CSS盤點8種CSS實現垂直居中

  • 須要居中元素爲單行文本,爲包含文本的元素設置大於font-sizeline-height
<p class="text">center text</p>

<style>
.text {
    line-height: 200px;
}
</style>
複製代碼

$javascript概念部分

DOM元素e的e.getAttribute(propName)和e.propName有什麼區別和聯繫

  • e.getAttribute(),是標準DOM操做文檔元素屬性的方法,具備通用性可在任意文檔上使用,返回元素在源文件中設置的屬性
  • e.propName一般是在HTML文檔中訪問特定元素的特性,瀏覽器解析元素後生成對應對象(如a標籤生成HTMLAnchorElement),這些對象的特性會根據特定規則結合屬性設置獲得,對於沒有對應特性的屬性,只能使用getAttribute進行訪問
  • e.getAttribute()返回值是源文件中設置的值,類型是字符串或者null(有的實現返回"")
  • e.propName返回值多是字符串、布爾值、對象、undefined等
  • 大部分attribute與property是一一對應關係,修改其中一個會影響另外一個,如id,title等屬性
  • 一些布爾屬性<input hidden/>的檢測設置須要hasAttribute和removeAttribute來完成,或者設置對應property
  • <a href="../index.html">link</a>中href屬性,轉換成property的時候須要經過轉換獲得完整URL
  • 一些attribute和property不是一一對應如:form控件中<input value="hello"/>對應的是defaultValue,修改或設置value property修改的是控件當前值,setAttribute修改value屬性不會改變value property

offsetWidth/offsetHeight,clientWidth/clientHeight與scrollWidth/scrollHeight的區別

  • offsetWidth/offsetHeight返回值包含content + padding + border,效果與e.getBoundingClientRect()相同
  • clientWidth/clientHeight返回值只包含content + padding,若是有滾動條,也不包含滾動條
  • scrollWidth/scrollHeight返回值包含content + padding + 溢出內容的尺寸

Measuring Element Dimension and Location with CSSOM in Windows Internet Explorer 9

元素尺寸

XMLHttpRequest通用屬性和方法

  1. readyState:表示請求狀態的整數,取值:
  • UNSENT(0):對象已建立
  • OPENED(1):open()成功調用,在這個狀態下,能夠爲xhr設置請求頭,或者使用send()發送請求
  • HEADERS_RECEIVED(2):全部重定向已經自動完成訪問,而且最終響應的HTTP頭已經收到
  • LOADING(3):響應體正在接收
  • DONE(4):數據傳輸完成或者傳輸產生錯誤
  1. onreadystatechange:readyState改變時調用的函數
  2. status:服務器返回的HTTP狀態碼(如,200, 404)
  3. statusText:服務器返回的HTTP狀態信息(如,OK,No Content)
  4. responseText:做爲字符串形式的來自服務器的完整響應
  5. responseXML: Document對象,表示服務器的響應解析成的XML文檔
  6. abort():取消異步HTTP請求
  7. getAllResponseHeaders(): 返回一個字符串,包含響應中服務器發送的所有HTTP報頭。每一個報頭都是一個用冒號分隔開的名/值對,而且使用一個回車/換行來分隔報頭行
  8. getResponseHeader(headerName):返回headName對應的報頭值
  9. open(method, url, asynchronous [, user, password]):初始化準備發送到服務器上的請求。method是HTTP方法,不區分大小寫;url是請求發送的相對或絕對URL;asynchronous表示請求是否異步;user和password提供身份驗證
  10. setRequestHeader(name, value):設置HTTP報頭
  11. send(body):對服務器請求進行初始化。參數body包含請求的主體部分,對於POST請求爲鍵值對字符串;對於GET請求,爲null

focus/blur與focusin/focusout的區別與聯繫

  1. focus/blur不冒泡,focusin/focusout冒泡
  2. focus/blur兼容性好,focusin/focusout在除FireFox外的瀏覽器下都保持良好兼容性,如需使用事件託管,可考慮在FireFox下使用事件捕獲elem.addEventListener('focus', handler, true)
  3. 可得到焦點的元素:
    1. window
    2. 連接被點擊或鍵盤操做
    3. 表單空間被點擊或鍵盤操做
    4. 設置tabindex屬性的元素被點擊或鍵盤操做

mouseover/mouseout與mouseenter/mouseleave的區別與聯繫

  1. mouseover/mouseout是標準事件,全部瀏覽器都支持;mouseenter/mouseleave是IE5.5引入的特有事件後來被DOM3標準採納,現代標準瀏覽器也支持
  2. mouseover/mouseout是冒泡事件;mouseenter/mouseleave不冒泡。須要爲多個元素監聽鼠標移入/出事件時,推薦mouseover/mouseout託管,提升性能
  3. 標準事件模型中event.target表示發生移入/出的元素,vent.relatedTarget對應移出/如元素;在老IE中event.srcElement表示發生移入/出的元素,event.toElement表示移出的目標元素,event.fromElement表示移入時的來源元素

例子:鼠標從div#target元素移出時進行處理,判斷邏輯以下:

<div id="target"><span>test</span></div>

<script type="text/javascript">
var target = document.getElementById('target');
if (target.addEventListener) {
  target.addEventListener('mouseout', mouseoutHandler, false);
} else if (target.attachEvent) {
  target.attachEvent('onmouseout', mouseoutHandler);
}

function mouseoutHandler(e) {
  e = e || window.event;
  var target = e.target || e.srcElement;

  // 判斷移出鼠標的元素是否爲目標元素
  if (target.id !== 'target') {
    return;
  }

  // 判斷鼠標是移出元素仍是移到子元素
  var relatedTarget = event.relatedTarget || e.toElement;
  while (relatedTarget !== target
    && relatedTarget.nodeName.toUpperCase() !== 'BODY') {
    relatedTarget = relatedTarget.parentNode;
  }

  // 若是相等,說明鼠標在元素內部移動
  if (relatedTarget === target) {
    return;
  }

  // 執行須要操做
  //alert('鼠標移出');

}
</script>
複製代碼

sessionStorage,localStorage,cookie區別

  1. 都會在瀏覽器端保存,有大小限制,同源限制
  2. cookie會在請求時發送到服務器,做爲會話標識,服務器可修改cookie;web storage不會發送到服務器
  3. cookie有path概念,子路徑能夠訪問父路徑cookie,父路徑不能訪問子路徑cookie
  4. 有效期:cookie在設置的有效期內有效,默認爲瀏覽器關閉;sessionStorage在窗口關閉前有效,localStorage長期有效,直到用戶刪除
  5. 共享:sessionStorage不能共享,localStorage在同源文檔之間共享,cookie在同源且符合path規則的文檔之間共享
  6. localStorage的修改會促發其餘文檔窗口的update事件
  7. cookie有secure屬性要求HTTPS傳輸
  8. 瀏覽器不能保存超過300個cookie,單個服務器不能超過20個,每一個cookie不能超過4k。web storage大小支持能達到5M

javascript跨域通訊

同源:兩個文檔同源需知足

  1. 協議相同
  2. 域名相同
  3. 端口相同

跨域通訊:js進行DOM操做、通訊時若是目標與當前窗口不知足同源條件,瀏覽器爲了安全會阻止跨域操做。跨域通訊一般有如下方法

  • 若是是log之類的簡單單項通訊,新建<img>,<script>,<link>,<iframe>元素,經過src,href屬性設置爲目標url。實現跨域請求
  • 若是請求json數據,使用<script>進行jsonp請求
  • 現代瀏覽器中多窗口通訊使用HTML5規範的targetWindow.postMessage(data, origin);其中data是須要發送的對象,origin是目標窗口的origin。window.addEventListener('message', handler, false);handler的event.data是postMessage發送來的數據,event.origin是發送窗口的origin,event.source是發送消息的窗口引用
  • 內部服務器代理請求跨域url,而後返回數據
  • 跨域請求數據,現代瀏覽器可以使用HTML5規範的CORS功能,只要目標服務器返回HTTP頭部**Access-Control-Allow-Origin: ***便可像普通ajax同樣訪問跨域資源

javascript有哪幾種數據類型

六種基本數據類型

  • undefined
  • null
  • string
  • boolean
  • number
  • symbol(ES6)

一種引用類型

  • Object

什麼閉包,閉包有什麼用

閉包是在某個做用域內定義的函數,它能夠訪問這個做用域內的全部變量。閉包做用域鏈一般包括三個部分:

  1. 函數自己做用域。
  2. 閉包定義時的做用域。
  3. 全局做用域。

閉包常見用途:

  1. 建立特權方法用於訪問控制
  2. 事件處理程序及回調

javascript有哪幾種方法定義函數

  1. 函數聲明表達式
  2. function操做符
  3. Function 構造函數
  4. ES6:arrow function

重要參考資料:MDN:Functions_and_function_scope

應用程序存儲和離線web應用

HTML5新增應用程序緩存,容許web應用將應用程序自身保存到用戶瀏覽器中,用戶離線狀態也能訪問。 1.爲html元素設置manifest屬性:<html manifest="myapp.appcache">,其中後綴名只是一個約定,真正識別方式是經過text/cache-manifest做爲MIME類型。因此須要配置服務器保證設置正確 2.manifest文件首行爲CACHE MANIFEST,其他就是要緩存的URL列表,每一個一行,相對路徑都相對於manifest文件的url。註釋以#開頭 3.url分爲三種類型:CACHE:爲默認類型。NETWORK:表示資源從不緩存。 FALLBACK:每行包含兩個url,第二個URL是指須要加載和存儲在緩存中的資源, 第一個URL是一個前綴。任何匹配該前綴的URL都不會緩存,若是從網絡中載入這樣的URL失敗的話,就會用第二個URL指定的緩存資源來替代。如下是一個文件例子:

CACHE MANIFEST

CACHE:
myapp.html
myapp.css
myapp.js

FALLBACK:
videos/ offline_help.html

NETWORK:
cgi/
複製代碼

客戶端存儲localStorage和sessionStorage

  • localStorage有效期爲永久,sessionStorage有效期爲頂層窗口關閉前
  • 同源文檔能夠讀取並修改localStorage數據,sessionStorage只容許同一個窗口下的文檔訪問,如經過iframe引入的同源文檔。
  • Storage對象一般被當作普通javascript對象使用:經過設置屬性來存取字符串值,也能夠經過setItem(key, value)設置getItem(key)讀取removeItem(key)刪除clear()刪除全部數據length表示已存儲的數據項數目key(index)返回對應索引的key
localStorage.setItem('x', 1); // storge x->1
localStorage.getItem('x); // return value of x // 枚舉全部存儲的鍵值對 for (var i = 0, len = localStorage.length; i < len; ++i ) { var name = localStorage.key(i); var value = localStorage.getItem(name); } localStorage.removeItem('x'); // remove x localStorage.clear(); // remove all data 複製代碼

cookie及其操做

  • cookie是web瀏覽器存儲的少許數據,最先設計爲服務器端使用,做爲HTTP協議的擴展實現。cookie數據會自動在瀏覽器和服務器之間傳輸。
  • 經過讀寫cookie檢測是否支持
  • cookie屬性有max-agepath, domainsecure
  • cookie默認有效期爲瀏覽器會話,一旦用戶關閉瀏覽器,數據就丟失,經過設置max-age=seconds屬性告訴瀏覽器cookie有效期
  • cookie做用域經過文檔源文檔路徑來肯定,經過pathdomain進行配置,web頁面同目錄或子目錄文檔均可訪問
  • 經過cookie保存數據的方法爲:爲document.cookie設置一個符合目標的字符串以下
  • 讀取document.cookie得到'; '分隔的字符串,key=value,解析獲得結果
document.cookie = 'name=qiu; max-age=9999; path=/; domain=domain; secure';

document.cookie = 'name=aaa; path=/; domain=domain; secure';
// 要改變cookie的值,須要使用相同的名字、路徑和域,新的值
// 來設置cookie,一樣的方法能夠用來改變有效期

// 設置max-age爲0能夠刪除指定cookie

//讀取cookie,訪問document.cookie返回鍵值對組成的字符串,
//不一樣鍵值對之間用'; '分隔。經過解析得到須要的值
複製代碼

cookieUtil.js:本身寫的cookie操做工具

javascript有哪些方法定義對象

  1. 對象字面量: var obj = {};
  2. 構造函數: var obj = new Object();
  3. Object.create(): var obj = Object.create(Object.prototype);

===運算符判斷相等的流程是怎樣的

  1. 若是兩個值不是相同類型,它們不相等
  2. 若是兩個值都是null或者都是undefined,它們相等
  3. 若是兩個值都是布爾類型true或者都是false,它們相等
  4. 若是其中有一個是NaN,它們不相等
  5. 若是都是數值型而且數值相等,他們相等, -0等於0
  6. 若是他們都是字符串而且在相同位置包含相同的16位值,他它們相等;若是在長度或者內容上不等,它們不相等;兩個字符串顯示結果相同可是編碼不一樣==和===都認爲他們不相等
  7. 若是他們指向相同對象、數組、函數,它們相等;若是指向不一樣對象,他們不相等

==運算符判斷相等的流程是怎樣的

  1. 若是兩個值類型相同,按照===比較方法進行比較
  2. 若是類型不一樣,使用以下規則進行比較
  3. 若是其中一個值是null,另外一個是undefined,它們相等
  4. 若是一個值是數字另外一個是字符串,將字符串轉換爲數字進行比較
  5. 若是有布爾類型,將true轉換爲1,false轉換爲0,而後用==規則繼續比較
  6. 若是一個值是對象,另外一個是數字或字符串,將對象轉換爲原始值而後用==規則繼續比較
  7. 其餘全部狀況都認爲不相等

對象到字符串的轉換步驟

  1. 若是對象有toString()方法,javascript調用它。若是返回一個原始值(primitive value如:string number boolean),將這個值轉換爲字符串做爲結果
  2. 若是對象沒有toString()方法或者返回值不是原始值,javascript尋找對象的valueOf()方法,若是存在就調用它,返回結果是原始值則轉爲字符串做爲結果
  3. 不然,javascript不能從toString()或者valueOf()得到一個原始值,此時throws a TypeError

對象到數字的轉換步驟

1. 若是對象有valueOf()方法而且返回元素值,javascript將返回值轉換爲數字做爲結果
2. 不然,若是對象有toString()而且返回原始值,javascript將返回結果轉換爲數字做爲結果
3. 不然,throws a TypeError
複製代碼

<,>,<=,>=的比較規則

全部比較運算符都支持任意類型,可是比較只支持數字和字符串,因此須要執行必要的轉換而後進行比較,轉換規則以下:

  1. 若是操做數是對象,轉換爲原始值:若是valueOf方法返回原始值,則使用這個值,不然使用toString方法的結果,若是轉換失敗則報錯
  2. 通過必要的對象到原始值的轉換後,若是兩個操做數都是字符串,按照字母順序進行比較(他們的16位unicode值的大小)
  3. 不然,若是有一個操做數不是字符串,將兩個操做數轉換爲數字進行比較

+運算符工做流程

  1. 若是有操做數是對象,轉換爲原始值
  2. 此時若是有一個操做數是字符串,其餘的操做數都轉換爲字符串並執行鏈接
  3. 不然:全部操做數都轉換爲數字並執行加法

函數內部arguments變量有哪些特性,有哪些屬性,如何將它轉換爲數組

  • arguments全部函數中都包含的一個局部變量,是一個類數組對象,對應函數調用時的實參。若是函數定義同名參數會在調用時覆蓋默認對象
  • arguments[index]分別對應函數調用時的實參,而且經過arguments修改實參時會同時修改實參
  • arguments.length爲實參的個數(Function.length表示形參長度)
  • arguments.callee爲當前正在執行的函數自己,使用這個屬性進行遞歸調用時需注意this的變化
  • arguments.caller爲調用當前函數的函數(已被遺棄)
  • 轉換爲數組:var args = Array.prototype.slice.call(arguments, 0);

DOM事件模型是如何的,編寫一個EventUtil工具類實現事件管理兼容

  • DOM事件包含捕獲(capture)和冒泡(bubble)兩個階段:捕獲階段事件從window開始觸發事件而後經過祖先節點一次傳遞到觸發事件的DOM元素上;冒泡階段事件從初始元素依次向祖先節點傳遞直到window
  • 標準事件監聽elem.addEventListener(type, handler, capture)/elem.removeEventListener(type, handler, capture):handler接收保存事件信息的event對象做爲參數,event.target爲觸發事件的對象,handler調用上下文this爲綁定監聽器的對象,event.preventDefault()取消事件默認行爲,event.stopPropagation()/event.stopImmediatePropagation()取消事件傳遞
  • 老版本IE事件監聽elem.attachEvent('on'+type, handler)/elem.detachEvent('on'+type, handler):handler不接收event做爲參數,事件信息保存在window.event中,觸發事件的對象爲event.srcElement,handler執行上下文this爲window使用閉包中調用handler.call(elem, event)可模仿標準模型,而後返回閉包,保證了監聽器的移除。event.returnValue爲false時取消事件默認行爲,event.cancleBubble爲true時取消時間傳播
  • 一般利用事件冒泡機制託管事件處理程序提升程序性能。
/**
 * 跨瀏覽器事件處理工具。只支持冒泡。不支持捕獲
 * @author  (qiu_deqing@126.com)
 */

var EventUtil = {
    getEvent: function (event) {
        return event || window.event;
    },
    getTarget: function (event) {
        return event.target || event.srcElement;
    },
    // 返回註冊成功的監聽器,IE中須要使用返回值來移除監聽器
    on: function (elem, type, handler) {
        if (elem.addEventListener) {
            elem.addEventListener(type, handler, false);
            return handler;
        } else if (elem.attachEvent) {
            var wrapper = function () {
              var event = window.event;
              event.target = event.srcElement;
              handler.call(elem, event);
            };
            elem.attachEvent('on' + type, wrapper);
            return wrapper;
        }
    },
    off: function (elem, type, handler) {
        if (elem.removeEventListener) {
            elem.removeEventListener(type, handler, false);
        } else if (elem.detachEvent) {
            elem.detachEvent('on' + type, handler);
        }
    },
    preventDefault: function (event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else if ('returnValue' in event) {
            event.returnValue = false;
        }
    },
    stopPropagation: function (event) {
        if (event.stopPropagation) {
            event.stopPropagation();
        } else if ('cancelBubble' in event) {
            event.cancelBubble = true;
        }
    },
    /**
     * keypress事件跨瀏覽器獲取輸入字符
     * 某些瀏覽器在一些特殊鍵上也觸發keypress,此時返回null
     **/
     getChar: function (event) {
        if (event.which == null) {
            return String.fromCharCode(event.keyCode);  // IE
        }
        else if (event.which != 0 && event.charCode != 0) {
            return String.fromCharCode(event.which);    // the rest
        }
        else {
            return null;    // special key
        }
     }
};
複製代碼

評價一下三種方法實現繼承的優缺點,並改進

function Shape() {}

function Rect() {}

// 方法1
Rect.prototype = new Shape();

// 方法2
Rect.prototype = Shape.prototype;

// 方法3
Rect.prototype = Object.create(Shape.prototype);

Rect.prototype.area = function () {
  // do something
};
複製代碼

方法1:

  1. 優勢:正確設置原型鏈實現繼承
  2. 優勢:父類實例屬性獲得繼承,原型鏈查找效率提升,也能爲一些屬性提供合理的默認值
  3. 缺點:父類實例屬性爲引用類型時,不恰當地修改會致使全部子類被修改
  4. 缺點:建立父類實例做爲子類原型時,可能沒法肯定構造函數須要的合理參數,這樣提供的參數繼承給子類沒有實際意義,當子類須要這些參數時應該在構造函數中進行初始化和設置
  5. 總結:繼承應該是繼承方法而不是屬性,爲子類設置父類實例屬性應該是經過在子類構造函數中調用父類構造函數進行初始化

方法2:

  1. 優勢:正確設置原型鏈實現繼承
  2. 缺點:父類構造函數原型與子類相同。修改子類原型添加方法會修改父類

方法3:

  1. 優勢:正確設置原型鏈且避免方法1.2中的缺點
  2. 缺點:ES5方法須要注意兼容性

改進:

  1. 全部三種方法應該在子類構造函數中調用父類構造函數實現實例屬性初始化
function Rect() {
    Shape.call(this);
}
複製代碼
  1. 用新建立的對象替代子類默認原型,設置Rect.prototype.constructor = Rect;保證一致性
  2. 第三種方法的polyfill:
function create(obj) {
    if (Object.create) {
        return Object.create(obj);
    }

    function f() {};
    f.prototype = obj;
    return new f();
}
複製代碼

$javascript編程部分

請用原生js實現一個函數,給頁面制定的任意一個元素添加一個透明遮罩(透明度可變,默認0.2),使這個區域點擊無效,要求兼容IE8+及各主流瀏覽器,遮罩層效果以下圖所示:

遮罩效果

<style>
#target {
    width: 200px;
    height: 300px;
    margin: 40px;
    background-color: tomato;
}
</style>

<div id="target"></div>

<script>
function addMask(elem, opacity) {
    opacity = opacity || 0.2;

    var rect = elem.getBoundingClientRect();
    var style = getComputedStyle(elem, null);

    var mask = document.createElement('div');
    mask.style.position = 'absolute';
    var marginLeft = parseFloat(style.marginLeft);
    mask.style.left = (elem.offsetLeft - marginLeft) + 'px';
    var marginTop = parseFloat(style.marginTop);
    mask.style.top = (elem.offsetTop - marginTop) + 'px';
    mask.style.zIndex = 9999;
    mask.style.opacity = '' + opacity;
    mask.style.backgroundColor = '#000';

    mask.style.width = (parseFloat(style.marginLeft) +
        parseFloat(style.marginRight) + rect.width) + 'px';
    mask.style.height = (parseFloat(style.marginTop) +
        parseFloat(style.marginBottom) + rect.height) + 'px';

    elem.parentNode.appendChild(mask);
}

var target = document.getElementById('target');
addMask(target);

target.addEventListener('click', function () {
    console.log('click');
}, false);
</script>
複製代碼

請用代碼寫出(今天是星期x)其中x表示當天是星期幾,若是當天是星期一,輸出應該是"今天是星期一"

var days = ['日','一','二','三','四','五','六'];
var date = new Date();

console.log('今天是星期' + days[date.getDay()]);
複製代碼

下面這段代碼想要循環延時輸出結果0 1 2 3 4,請問輸出結果是否正確,若是不正確,請說明爲何,並修改循環內的代碼使其輸出正確結果

for (var i = 0; i < 5; ++i) {
  setTimeout(function () {
    console.log(i + ' ');
  }, 100);
}
複製代碼

不能輸出正確結果,由於循環中setTimeout接受的參數函數經過閉包訪問變量i。javascript運行環境爲單線程,setTimeout註冊的函數須要等待線程空閒才能執行,此時for循環已經結束,i值爲5.五個定時輸出都是5 修改方法:將setTimeout放在函數當即調用表達式中,將i值做爲參數傳遞給包裹函數,建立新閉包

for (var i = 0; i < 5; ++i) {
  (function (i) {
    setTimeout(function () {
      console.log(i + ' ');
    }, 100);
  }(i));
}
複製代碼

現有一個Page類,其原型對象上有許多以post開頭的方法(如postMsg);另有一攔截函數chekc,只返回ture或false.請設計一個函數,該函數應批量改造原Page的postXXX方法,在保留其原有功能的同時,爲每一個postXXX方法增長攔截驗證功能,當chekc返回true時繼續執行原postXXX方法,返回false時再也不執行原postXXX方法

function Page() {}

Page.prototype = {
  constructor: Page,

  postA: function (a) {
    console.log('a:' + a);
  },
  postB: function (b) {
    console.log('b:' + b);
  },
  postC: function (c) {
    console.log('c:' + c);
  },
  check: function () {
    return Math.random() > 0.5;
  }
}

function checkfy(obj) {
  for (var key in obj) {
    if (key.indexOf('post') === 0 && typeof obj[key] === 'function') {
      (function (key) {
        var fn = obj[key];
        obj[key] = function () {
          if (obj.check()) {
            fn.apply(obj, arguments);
          }
        };
      }(key));
    }
  }
} // end checkfy()

checkfy(Page.prototype);

var obj = new Page();

obj.postA('checkfy');
obj.postB('checkfy');
obj.postC('checkfy');
複製代碼

完成下面的tool-tip

xxx

編寫javascript深度克隆函數deepClone

function deepClone(obj) {
    var _toString = Object.prototype.toString;

    // null, undefined, non-object, function
    if (!obj || typeof obj !== 'object') {
        return obj;
    }

    // DOM Node
    if (obj.nodeType && 'cloneNode' in obj) {
        return obj.cloneNode(true);
    }

    // Date
    if (_toString.call(obj) === '[object Date]') {
        return new Date(obj.getTime());
    }

    // RegExp
    if (_toString.call(obj) === '[object RegExp]') {
        var flags = [];
        if (obj.global) { flags.push('g'); }
        if (obj.multiline) { flags.push('m'); }
        if (obj.ignoreCase) { flags.push('i'); }

        return new RegExp(obj.source, flags.join(''));
    }

    var result = Array.isArray(obj) ? [] :
        obj.constructor ? new obj.constructor() : {};

    for (var key in obj ) {
        result[key] = deepClone(obj[key]);
    }

    return result;
}

function A() {
    this.a = a;
}

var a = {
    name: 'qiu',
    birth: new Date(),
    pattern: /qiu/gim,
    container: document.body,
    hobbys: ['book', new Date(), /aaa/gim, 111]
};

var c = new A();
var b = deepClone(c);
console.log(c.a === b.a);
console.log(c, b);
複製代碼

補充代碼,鼠標單擊Button1後將Button1移動到Button2的後面

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>TEst</title>
</head>
<body>

<div>
   <input type="button" id ="button1" value="1" />
   <input type="button" id ="button2" value="2" />
</div>

<script type="text/javascript">
    var btn1 = document.getElementById('button1');
    var btn2 = document.getElementById('button2');

    addListener(btn1, 'click', function (event) {
        btn1.parentNode.insertBefore(btn2, btn1);
    });

    function addListener(elem, type, handler) {
        if (elem.addEventListener) {
            elem.addEventListener(type, handler, false);
            return handler;
        } else if (elem.attachEvent) {
            function wrapper() {
                var event = window.event;
                event.target = event.srcElement;
                handler.call(elem, event);
            }
            elem.attachEvent('on' + type, wrapper);
            return wrapper;
        }
    }

</script>
</body>
</html>
複製代碼

網頁中實現一個計算當年還剩多少時間的倒數計時程序,要求網頁上實時動態顯示"××年還剩××天××時××分××秒"

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>TEst</title>
</head>
<body>

    <span id="target"></span>


<script type="text/javascript">
    // 爲了簡化。每個月默認30天
    function getTimeString() {
        var start = new Date();
        var end = new Date(start.getFullYear() + 1, 0, 1);
        var elapse = Math.floor((end - start) / 1000);

        var seconds = elapse % 60 ;
        var minutes = Math.floor(elapse / 60) % 60;
        var hours = Math.floor(elapse / (60 * 60)) % 24;
        var days = Math.floor(elapse / (60 * 60 * 24)) % 30;
        var months = Math.floor(elapse / (60 * 60 * 24 * 30)) % 12;
        var years = Math.floor(elapse / (60 * 60 * 24 * 30 * 12));

        return start.getFullYear() + '年還剩' + years + '年' + months + '月' + days + '日'
            + hours + '小時' + minutes + '分' + seconds + '秒';
    }

    function domText(elem, text) {
        if (text == undefined) {

            if (elem.textContent) {
                return elem.textContent;
            } else if (elem.innerText) {
                return elem.innerText;
            }
        } else {
            if (elem.textContent) {
                elem.textContent = text;
            } else if (elem.innerText) {
                elem.innerText = text;
            } else {
                elem.innerHTML = text;
            }
        }
    }

    var target = document.getElementById('target');

    setInterval(function () {
        domText(target, getTimeString());
    }, 1000)
</script>

</body>
</html>
複製代碼

完成一個函數,接受數組做爲參數,數組元素爲整數或者數組,數組元素包含整數或數組,函數返回扁平化後的數組

如:[1, [2, [ [3, 4], 5], 6]] => [1, 2, 3, 4, 5, 6]

var data =  [1, [2, [ [3, 4], 5], 6]];

    function flat(data, result) {
        var i, d, len;
        for (i = 0, len = data.length; i < len; ++i) {
            d = data[i];
            if (typeof d === 'number') {
                result.push(d);
            } else {
                flat(d, result);
            }
        }
    }

    var result = [];
    flat(data, result);

    console.log(result);
複製代碼

如何判斷一個對象是否爲數組

若是瀏覽器支持Array.isArray()能夠直接判斷不然需進行必要判斷

/**
 * 判斷一個對象是不是數組,參數不是對象或者不是數組,返回false
 *
 * @param {Object} arg 須要測試是否爲數組的對象
 * @return {Boolean} 傳入參數是數組返回true,不然返回false
 */
function isArray(arg) {
    if (typeof arg === 'object') {
        return Object.prototype.toString.call(arg) === '[object Array]';
    }
    return false;
}
複製代碼

請評價如下事件監聽器代碼並給出改進意見

if (window.addEventListener) {
  var addListener = function (el, type, listener, useCapture) {
    el.addEventListener(type, listener, useCapture);
  };
}
else if (document.all) {
  addListener = function (el, type, listener) {
    el.attachEvent('on' + type, function () {
      listener.apply(el);
    });
  };
}
複製代碼

做用:瀏覽器功能檢測實現跨瀏覽器DOM事件綁定

優勢:

  1. 測試代碼只運行一次,根據瀏覽器肯定綁定方法
  2. 經過listener.apply(el)解決IE下監聽器this與標準不一致的地方
  3. 在瀏覽器不支持的狀況下提供簡單的功能,在標準瀏覽器中提供捕獲功能

缺點:

  1. document.all做爲IE檢測不可靠,應該使用if(el.attachEvent)
  2. addListener在不一樣瀏覽器下API不同
  3. listener.apply使this與標準一致但監聽器沒法移除
  4. 未解決IE下listener參數event。 target問題

改進:

var addListener;

if (window.addEventListener) {
  addListener = function (el, type, listener, useCapture) {
    el.addEventListener(type, listener, useCapture);
    return listener;
  };
}
else if (window.attachEvent) {
  addListener = function (el, type, listener) {
    // 標準化this,event,target
    var wrapper = function () {
      var event = window.event;
      event.target = event.srcElement;
      listener.call(el, event);
    };

    el.attachEvent('on' + type, wrapper);
    return wrapper;
    // 返回wrapper。調用者能夠保存,之後remove
  };
}
複製代碼

如何判斷一個對象是否爲函數

/**
 * 判斷對象是否爲函數,若是當前運行環境對可調用對象(如正則表達式)
 * 的typeof返回'function',採用通用方法,不然採用優化方法
 *
 * @param {Any} arg 須要檢測是否爲函數的對象
 * @return {boolean} 若是參數是函數,返回true,不然false
 */
function isFunction(arg) {
    if (arg) {
        if (typeof (/./) !== 'function') {
            return typeof arg === 'function';
        } else {
            return Object.prototype.toString.call(arg) === '[object Function]';
        }
    } // end if
    return false;
}
複製代碼

編寫一個函數接受url中query string爲參數,返回解析後的Object,query string使用application/x-www-form-urlencoded編碼

/**
 * 解析query string轉換爲對象,一個key有多個值時生成數組
 *
 * @param {String} query 須要解析的query字符串,開頭能夠是?,
 * 按照application/x-www-form-urlencoded編碼
 * @return {Object} 參數解析後的對象
 */
function parseQuery(query) {
    var result = {};

    // 若是不是字符串返回空對象
    if (typeof query !== 'string') {
        return result;
    }

    // 去掉字符串開頭可能帶的?
    if (query.charAt(0) === '?') {
        query = query.substring(1);
    }

    var pairs = query.split('&');
    var pair;
    var key, value;
    var i, len;

    for (i = 0, len = pairs.length; i < len; ++i) {
        pair = pairs[i].split('=');
        // application/x-www-form-urlencoded編碼會將' '轉換爲+
        key = decodeURIComponent(pair[0]).replace(/\+/g, ' ');
        value = decodeURIComponent(pair[1]).replace(/\+/g, ' ');

        // 若是是新key,直接添加
        if (!(key in result)) {
            result[key] = value;
        }
        // 若是key已經出現一次以上,直接向數組添加value
        else if (isArray(result[key])) {
            result[key].push(value);
        }
        // key第二次出現,將結果改成數組
        else {
            var arr = [result[key]];
            arr.push(value);
            result[key] = arr;
        } // end if-else
    } // end for

    return result;
}

function isArray(arg) {
    if (arg && typeof arg === 'object') {
        return Object.prototype.toString.call(arg) === '[object Array]';
    }
    return false;
}
/**
console.log(parseQuery('sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8'));
 */
複製代碼

解析一個完整的url,返回Object包含域與window.location相同

/**
 * 解析一個url並生成window.location對象中包含的域
 * location:
 * {
 *      href: '包含完整的url',
 *      origin: '包含協議到pathname以前的內容',
 *      protocol: 'url使用的協議,包含末尾的:',
 *      username: '用戶名', // 暫時不支持
 *      password: '密碼',  // 暫時不支持
 *      host: '完整主機名,包含:和端口',
 *      hostname: '主機名,不包含端口'
 *      port: '端口號',
 *      pathname: '服務器上訪問資源的路徑/開頭',
 *      search: 'query string,?開頭',
 *      hash: '#開頭的fragment identifier'
 * }
 *
 * @param {string} url 須要解析的url
 * @return {Object} 包含url信息的對象
 */
function parseUrl(url) {
    var result = {};
    var keys = ['href', 'origin', 'protocol', 'host',
                'hostname', 'port', 'pathname', 'search', 'hash'];
    var i, len;
    var regexp = /(([^:]+:)\/\/(([^:\/\?#]+)(:\d+)?))(\/[^?#]*)?(\?[^#]*)?(#.*)?/;

    var match = regexp.exec(url);

    if (match) {
        for (i = keys.length - 1; i >= 0; --i) {
            result[keys[i]] = match[i] ? match[i] : '';
        }
    }

    return result;
}
複製代碼

完成函數getViewportSize返回指定窗口的視口尺寸

/**
* 查詢指定窗口的視口尺寸,若是不指定窗口,查詢當前窗口尺寸
**/
function getViewportSize(w) {
    w = w || window;

    // IE9及標準瀏覽器中可以使用此標準方法
    if ('innerHeight' in w) {
        return {
            width: w.innerWidth,
            height: w.innerHeight
        };
    }

    var d = w.document;
    // IE 8及如下瀏覽器在標準模式下
    if (document.compatMode === 'CSS1Compat') {
        return {
            width: d.documentElement.clientWidth,
            height: d.documentElement.clientHeight
        };
    }

    // IE8及如下瀏覽器在怪癖模式下
    return {
        width: d.body.clientWidth,
        height: d.body.clientHeight
    };
}
複製代碼

完成函數getScrollOffset返回窗口滾動條偏移量

/**
 * 獲取指定window中滾動條的偏移量,如未指定則獲取當前window
 * 滾動條偏移量
 *
 * @param {window} w 須要獲取滾動條偏移量的窗口
 * @return {Object} obj.x爲水平滾動條偏移量,obj.y爲豎直滾動條偏移量
 */
function getScrollOffset(w) {
    w =  w || window;
    // 若是是標準瀏覽器
    if (w.pageXOffset != null) {
        return {
            x: w.pageXOffset,
            y: w.pageYOffset
        };
    }

    // 老版本IE,根據兼容性不一樣訪問不一樣元素
    var d = w.document;
    if (d.compatMode === 'CSS1Compat') {
        return {
            x: d.documentElement.scrollLeft,
            y: d.documentElement.scrollTop
        }
    }

    return {
        x: d.body.scrollLeft,
        y: d.body.scrollTop
    };
}
複製代碼

現有一個字符串richText,是一段富文本,須要顯示在頁面上.有個要求,須要給其中只包含一個img元素的p標籤增長一個叫pic的class.請編寫代碼實現.可使用jQuery或KISSY.

function richText(text) {
    var div = document.createElement('div');
    div.innerHTML = text;
    var p = div.getElementsByTagName('p');
    var i, len;

    for (i = 0, len = p.length; i < len; ++i) {
        if (p[i].getElementsByTagName('img').length === 1) {
            p[i].classList.add('pic');
        }
    }

    return div.innerHTML;
}
複製代碼

請實現一個Event類,繼承自此類的對象都會擁有兩個方法on,off,once和trigger

function Event() {
    if (!(this instanceof Event)) {
        return new Event();
    }
    this._callbacks = {};
}
Event.prototype.on = function (type, handler) {
    this_callbacks = this._callbacks || {};
    this._callbacks[type] = this.callbacks[type] || [];
    this._callbacks[type].push(handler);

    return this;
};

Event.prototype.off = function (type, handler) {
    var list = this._callbacks[type];

    if (list) {
        for (var i = list.length; i >= 0; --i) {
            if (list[i] === handler) {
                list.splice(i, 1);
            }
        }
    }

    return this;
};

Event.prototype.trigger = function (type, data) {
    var list = this._callbacks[type];

    if (list) {
        for (var i = 0, len = list.length; i < len; ++i) {
            list[i].call(this, data);
        }
    }
};

Event.prototype.once = function (type, handler) {
    var self = this;

    function wrapper() {
        handler.apply(self, arguments);
        self.off(type, wrapper);
    }
    this.on(type, wrapper);
    return this;
};
複製代碼

編寫一個函數將列表子元素順序反轉

<ul id="target">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>

<script>
    var target = document.getElementById('target');
    var i;
    var frag = document.createDocumentFragment();

    for (i = target.children.length - 1; i &gt;= 0; --i) {
        frag.appendChild(target.children[i]);
    }
    target.appendChild(frag);
</script>
複製代碼

如下函數的做用是?空白區域應該填寫什麼

// define
(function (window) {
    function fn(str) {
        this.str = str;
    }

    fn.prototype.format = function () {
        var arg = __1__;
        return this.str.replace(__2__, function (a, b) {
            return arg[b] || '';
        });
    };

    window.fn = fn;
})(window);

// use
(function () {
    var t = new fn('<p><a href="{0}">{1}</a><span>{2}</span></p>');
    console.log(t.format('http://www.alibaba.com', 'Alibaba', 'Welcome'));
})();
複製代碼

define部分定義一個簡單的模板類,使用{}做爲轉義標記,中間的數字表示替換目標,format實參用來替換模板內標記 橫線處填:

  1. Array.prototype.slice.call(arguments, 0)
  2. /\{\s*(\d+)\s*\}/g

編寫一個函數實現form的序列化(即將一個表單中的鍵值序列化爲可提交的字符串)

<form id="target">
    <select name="age">
        <option value="aaa">aaa</option>
        <option value="bbb" selected>bbb</option>
    </select>
    <select name="friends" multiple>
        <option value="qiu" selected>qiu</option>
        <option value="de">de</option>
        <option value="qing" selected>qing</option>
    </select>
    <input name="name" value="qiudeqing">
    <input type="password" name="password" value="11111">
    <input type="hidden" name="salery" value="3333">
    <textarea name="description">description</textarea>
    <input type="checkbox" name="hobby" checked value="football">Football
    <input type="checkbox" name="hobby" value="basketball">Basketball
    <input type="radio" name="sex" checked value="Female">Female
    <input type="radio" name="sex" value="Male">Male
</form>


<script>

/**
 * 將一個表單元素序列化爲可提交的字符串
 *
 * @param {FormElement} form 須要序列化的表單元素
 * @return {string} 表單序列化後的字符串
 */
function serializeForm(form) {
  if (!form || form.nodeName.toUpperCase() !== 'FORM') {
    return;
  }

  var result = [];

  var i, len;
  var field, fieldName, fieldType;

  for (i = 0, len = form.length; i < len; ++i) {
    field = form.elements[i];
    fieldName = field.name;
    fieldType = field.type;

    if (field.disabled || !fieldName) {
      continue;
    } // enf if

    switch (fieldType) {
      case 'text':
      case 'password':
      case 'hidden':
      case 'textarea':
        result.push(encodeURIComponent(fieldName) + '=' +
            encodeURIComponent(field.value));
        break;

      case 'radio':
      case 'checkbox':
        if (field.checked) {
          result.push(encodeURIComponent(fieldName) + '=' +
            encodeURIComponent(field.value));
        }
        break;

      case 'select-one':
      case 'select-multiple':
        for (var j = 0, jLen = field.options.length; j < jLen; ++j) {
          if (field.options[j].selected) {
            result.push(encodeURIComponent(fieldName) + '=' +
              encodeURIComponent(field.options[j].value || field.options[j].text));
          }
        } // end for
        break;

      case 'file':
      case 'submit':
        break; // 是否處理?

      default:
        break;
    } // end switch
  } // end for

    return result.join('&');
}

var form = document.getElementById('target');
console.log(serializeForm(form));
</script>
複製代碼

使用原生javascript給下面列表中的li節點綁定點擊事件,點擊時建立一個Object對象,兼容IE和標準瀏覽器

<ul id="nav">
    <li><a href="http://11111">111</a></li>
    <li><a href="http://2222">222</a></li>
    <li><a href="http://333">333</a></li>
    <li><a href="http://444">444</a></li>
</ul>

Object:
{
    "index": 1,
    "name": "111",
    "link": "http://1111"
}
複製代碼

script:

var EventUtil = {
    getEvent: function (event) {
        return event || window.event;
    },
    getTarget: function (event) {
        return event.target || event.srcElement;
    },
    // 返回註冊成功的監聽器,IE中須要使用返回值來移除監聽器
    on: function (elem, type, handler) {
        if (elem.addEventListener) {
            elem.addEventListener(type, handler, false);
            return handler;
        } else if (elem.attachEvent) {
            function wrapper(event) {
                return handler.call(elem, event);
            };
            elem.attachEvent('on' + type, wrapper);
            return wrapper;
        }
    },
    off: function (elem, type, handler) {
        if (elem.removeEventListener) {
            elem.removeEventListener(type, handler, false);
        } else if (elem.detachEvent) {
            elem.detachEvent('on' + type, handler);
        }
    },
    preventDefault: function (event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else if ('returnValue' in event) {
            event.returnValue = false;
        }
    },
    stopPropagation: function (event) {
        if (event.stopPropagation) {
            event.stopPropagation();
        } else if ('cancelBubble' in event) {
            event.cancelBubble = true;
        }
    }
};
var DOMUtil = {
    text: function (elem) {
        if ('textContent' in elem) {
            return elem.textContent;
        } else if ('innerText' in elem) {
            return elem.innerText;
        }
    },
    prop: function (elem, propName) {
        return elem.getAttribute(propName);
    }
};

var nav = document.getElementById('nav');

EventUtil.on(nav, 'click', function (event) {
    var event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);

    var children = this.children;
    var i, len;
    var anchor;
    var obj = {};

    for (i = 0, len = children.length; i < len; ++i) {
        if (children[i] === target) {
            obj.index = i + 1;
            anchor = target.getElementsByTagName('a')[0];
            obj.name = DOMUtil.text(anchor);
            obj.link = DOMUtil.prop(anchor, 'href');
        }
    }

    alert('index: ' + obj.index + ' name: ' + obj.name +
        ' link: ' + obj.link);
});
複製代碼

有一個大數組,var a = ['1', '2', '3', ...];a的長度是100,內容填充隨機整數的字符串.請先構造此數組a,而後設計一個算法將其內容去重

/**
    * 數組去重
    **/
    function normalize(arr) {
        if (arr && Array.isArray(arr)) {
            var i, len, map = {};
            for (i = arr.length; i >= 0; --i) {
                if (arr[i] in map) {
                    arr.splice(i, 1);
                } else {
                    map[arr[i]] = true;
                }
            }
        }
        return arr;
    }

    /**
    * 用100個隨機整數對應的字符串填充數組。
    **/
    function fillArray(arr, start, end) {
        start = start == undefined ? 1 : start;
        end = end == undefined ?  100 : end;

        if (end <= start) {
            end = start + 100;
        }

        var width = end - start;
        var i;
        for (i = 100; i >= 1; --i) {
            arr.push('' + (Math.floor(Math.random() * width) + start));
        }
        return arr;
    }

    var input = [];
    fillArray(input, 1, 100);
    input.sort(function (a, b) {
        return a - b;
    });
    console.log(input);

    normalize(input);
    console.log(input);
複製代碼

轉載淶源: github.com/qiu-deqing/…

相關文章
相關標籤/搜索