我的收集的前端知識點、面試題和答案,參考答案僅表明我的觀點,方便複習,目錄以下,經過文檔內搜索目錄可快速定位章節javascript
<img>
的title
和alt
有什麼區別title
是global attributes之一,用於爲元素提供附加的 advisory information。一般當鼠標滑動到元素上的時候顯示。alt
是<img>
的特有屬性,是圖片內容的等價描述,用於圖片沒法加載時顯示、讀屏器閱讀圖片。可提圖片高可訪問性,除了純裝飾圖片外都必須設置有意義的值,搜索引擎會重點分析。<!doctype>
聲明必須處於 HTML 文檔的頭部,在<html>
標籤以前,HTML5 中不區分大小寫<!doctype>
聲明不是一個 HTML 標籤,是一個用於告訴瀏覽器當前 HTMl 版本的指令<!doctype>
聲明指向一個 DTD,因爲 HTML4.01 基於 SGML,因此 DTD 指定了標記規則以保證瀏覽器正確渲染內容常見 dotype:css
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<!doctype html>
參考資料: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, linkhidden
: 表示一個元素是否與文檔。樣式上會致使元素不顯示,可是不能用這個屬性實現樣式效果id
: 元素 id,文檔內惟一lang
: 元素內容的的語言spellcheck
: 是否啓動拼寫和語法檢查style
: 行內 css 樣式tabindex
: 設置元素能夠得到焦點,經過 tab 能夠導航title
: 元素相關的建議信息translate
: 元素和子孫節點內容是否須要本地化web 語義化是指經過 HTML 標記表示頁面包含的信息,包含了 HTML 標籤的語義化和 css 命名的語義化。 HTML 標籤的語義化是指:經過使用包含語義的標籤(如 h1-h6)恰當地表示文檔結構 css 命名的語義化是指:爲 html 標籤添加有意義的 class,id 補充未表達的語義,如Microformat經過添加符合規則的 class 描述信息 爲何須要語義化:前端
Expires
和Cache-Control
:
script
,meta
這樣自己不可見的標籤。2)被 css 隱藏的節點,如display: none
rfc2616中進行了定義:java
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
rfc2616中進行了定義:node
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 Site:git
content 方面github
Server 方面web
Cookie 方面面試
css 方面
Javascript 方面
圖片方面
移動方面
漸進加強是指在 web 設計時強調可訪問性、語義化 HTML 標籤、外部樣式表和腳本。保證全部人都能訪問頁面的基本內容和功能同時爲高級瀏覽器和高帶寬用戶提供更好的用戶體驗。核心原則以下:
參考RFC 2616
概念:將多個小圖片拼接到一個圖片中。經過 background-position 和元素尺寸調節須要顯示的背景圖案。
優勢:
缺點:
display: none;
與visibility: hidden;
的區別聯繫:它們都能讓元素不可見
區別:
原理:利用不一樣瀏覽器對 CSS 的支持和解析結果不同編寫針對特定瀏覽器樣式。常見的 hack 有 1)屬性 hack。2)選擇器 hack。3)IE 條件註釋
<!--[if IE 6]> Special instructions for IE 6 here <![endif]-->
/***** 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; }
/* 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: 以 specified value 根據規範定義的行爲進行計算,一般將相對值計算爲絕對值,例如 em 根據 font-size 進行計算。一些使用百分數而且須要佈局來決定最終值的屬性,如 width,margin。百分數就直接做爲 computed value。line-height 的無單位值也直接做爲 computed value。這些值將在計算 used value 時獲得絕對值。computed value 的主要做用是用於繼承
used value:屬性計算後的最終值,對於大多數屬性能夠經過 window.getComputedStyle 得到,尺寸值單位爲像素。如下屬性依賴於佈局,
link
與@import
的區別link
是 HTML 方式, @import
是 CSS 方式link
最大限度支持並行下載,@import
過多嵌套致使串行下載,出現FOUClink
能夠經過rel="alternate stylesheet"
指定候選樣式link
支持早於@import
,可使用@import
對老瀏覽器隱藏樣式@import
必須在樣式規則以前,能夠在 css 文件中引用其餘文件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
屬性生效
參考資料: 選擇正確的圖片格式 GIF:
JPEG:
PNG:
.target { min-height: 100px; height: auto !important; height: 100px; // IE6下內容高度超過會自動擴展高度 }
ol
內li
的序號全爲 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>
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>
opacity
,解決辦法:.opacity { opacity: 0.4 filter: alpha(opacity=60); /* for IE5-7 */ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; /* for IE 8*/ }
height
小於font-size
時高度值爲font-size
,解決辦法:font-size: 0;
display: inline-block
解決辦法:設置 inline 並觸發 hasLayoutdisplay: inline-block; *display: inline; *zoom: 1;
display: inline;
這樣解決問題且無任何反作用:css 標準規定浮動元素 display:inline 會自動調整爲 blocktext-align: center;
clear: both
/** * 在標準瀏覽器下使用 * 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; }
Flash Of Unstyled Content:用戶定義樣式表加載以前瀏覽器使用默認樣式顯示文檔,用戶樣式加載渲染以後再重新顯示文檔,形成頁面閃爍。解決方法:把樣式表放到文檔的head
建立規則:
float
不是none
)position
取值爲absolute
或fixed
)display
取值爲inline-block
,table-cell
, table-caption
,flex
, inline-flex
之一的元素overflow
不是visible
的元素做用:
display
爲 none,那麼 position 和 float 都不起做用,這種狀況下元素不產生框display
毗鄰的兩個或多個margin
會合併成一個 margin,叫作外邊距摺疊。規則以下:
根元素的包含塊叫作初始包含塊,在連續媒體中他的尺寸與 viewport 相同而且 anchored at the canvas origin;對於 paged media,它的尺寸等於 page area。初始包含塊的 direction 屬性與根元素相同。
position
爲relative
或者static
的元素,它的包含塊由最近的塊級(display
爲block
,list-item
, table
)祖先元素的內容框組成
若是元素position
爲fixed
。對於連續媒體,它的包含塊爲 viewport;對於 paged media,包含塊爲 page area
若是元素position
爲absolute
,它的包含塊由祖先元素中最近一個position
爲relative
,absolute
或者fixed
的元素產生,規則以下:
若是找不到定位的祖先元素,包含塊爲初始包含塊
z 軸上的默認層疊順序以下(從下到上):
如何建立 stacking context:
text-align: center;
便可實現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>
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>
<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>
<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-size
的line-height
:<p class="text">center text</p> <style> .text { line-height: 200px; } </style>
<input hidden/>
的檢測設置須要 hasAttribute 和 removeAttribute 來完成,或者設置對應 property<a href="../index.html">link</a>
中 href 屬性,轉換成 property 的時候須要經過轉換獲得完整 URL<input value="hello"/>
對應的是 defaultValue,修改或設置 value property 修改的是控件當前值,setAttribute 修改 value 屬性不會改變 value propertyMeasuring Element Dimension and Location with CSSOM in Windows Internet Explorer 9
readyState
:表示請求狀態的整數,取值:onreadystatechange
:readyState 改變時調用的函數status
:服務器返回的 HTTP 狀態碼(如,200, 404)statusText
:服務器返回的 HTTP 狀態信息(如,OK,No Content)responseText
:做爲字符串形式的來自服務器的完整響應responseXML
: Document 對象,表示服務器的響應解析成的 XML 文檔abort()
:取消異步 HTTP 請求getAllResponseHeaders()
: 返回一個字符串,包含響應中服務器發送的所有 HTTP 報頭。每一個報頭都是一個用冒號分隔開的名/值對,而且使用一個回車/換行來分隔報頭行getResponseHeader(headerName)
:返回 headName 對應的報頭值open(method, url, asynchronous [, user, password])
:初始化準備發送到服務器上的請求。method 是 HTTP 方法,不區分大小寫;url 是請求發送的相對或絕對 URL;asynchronous 表示請求是否異步;user 和 password 提供身份驗證setRequestHeader(name, value)
:設置 HTTP 報頭send(body)
:對服務器請求進行初始化。參數 body 包含請求的主體部分,對於 POST 請求爲鍵值對字符串;對於 GET 請求,爲 nulltabindex
屬性的元素被點擊或鍵盤操做例子:鼠標從 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>
同源:兩個文檔同源需知足
跨域通訊:js 進行 DOM 操做、通訊時若是目標與當前窗口不知足同源條件,瀏覽器爲了安全會阻止跨域操做。跨域通訊一般有如下方法
<img>
,<script>
,<link>
,<iframe>
元素,經過 src,href 屬性設置爲目標 url。實現跨域請求<script>
進行 jsonp 請求Access-Control-Allow-Origin: *
**便可像普通 ajax 同樣訪問跨域資源六種基本數據類型
一種引用類型
閉包是在某個做用域內定義的函數,它能夠訪問這個做用域內的全部變量。閉包做用域鏈一般包括三個部分:
閉包常見用途:
重要參考資料:MDN:Functions_and_function_scope
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.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
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 操做工具
var obj = {};
var obj = new Object();
var obj = Object.create(Object.prototype);
1. 若是對象有valueOf()方法而且返回元素值,javascript將返回值轉換爲數字做爲結果 2. 不然,若是對象有toString()而且返回原始值,javascript將返回結果轉換爲數字做爲結果 3. 不然,throws a TypeError
全部比較運算符都支持任意類型,可是比較只支持數字和字符串,因此須要執行必要的轉換而後進行比較,轉換規則以下:
var args = Array.prototype.slice.call(arguments, 0);
/** * 跨瀏覽器事件處理工具。只支持冒泡。不支持捕獲 * @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:
方法 2:
方法 3:
改進:
function Rect() { Shape.call(this); }
Rect.prototype.constructor = Rect;
保證一致性function create(obj) { if (Object.create) { return Object.create(obj); } function f() {}; f.prototype = obj; return new f(); }
<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>
var days = ['日','一','二','三','四','五','六']; var date = new Date(); console.log('今天是星期' + days[date.getDay()]);
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)); }
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');
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);
<!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 事件綁定
優勢:
listener.apply(el)
解決 IE 下監聽器 this 與標準不一致的地方缺點:
listener.apply
使 this 與標準一致但監聽器沒法移除改進:
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; }
/** * 解析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並生成window.location對象中包含的域 * location: * { * href: '包含完整的url', * origin: '包含協議到pathname以前的內容', * protocol: 'url使用的協議,包含末尾的:', * username: '用戶名', // 暫時不支持 * password: '密碼', // 暫時不支持 * host: '完整主機名,包含:和端口', * hostname: '主機名,不包含端口' * port: '端口號', * pathname: '服務器上訪問資源的路徑/開頭', * search: 'query string,?開頭', * hash: '#開頭的fragment identifier' * }