原文:http://segmentfault.com/a/1190000002562454javascript
轉自 : https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions/Questions-and-Answersphp
1,去掉或者丟失樣式的時候可以讓頁面呈現出清晰的結構 2,有利於SEO:和搜索引擎創建良好溝通,有助於爬蟲抓取更多的有效信息:爬蟲依賴於標籤來肯定上下文和各個關鍵字的權重; 3,方便其餘設備解析(如屏幕閱讀器、盲人閱讀器、移動設備)以意義的方式來渲染網頁; 4,便於團隊開發和維護,語義化更具可讀性,是下一步吧網頁的重要動向,遵循W3C標準的團隊都遵循這個標準,能夠減小差別化。
答: css
1.id選擇器( # myid) 2.類選擇器(.myclassname) 3.標籤選擇器(div, h1, p) 4.相鄰選擇器(h1 + p):選擇的是緊鄰在h1後面的p元素 5.子選擇器(ul > li) : 就選擇兒子,不選擇孫子輩的 6.後代選擇器(li a) : 選擇全部的兒子,孫子,重孫子等等 7.通配符選擇器( * ):選擇全部 8.屬性選擇器(a[rel = "external"]) 9.僞類選擇器(a: hover, li:nth-child) 可繼承的樣式: font-size font-family color, text-indent; 不可繼承的樣式:border padding margin width height ; 優先級就近原則,同權重狀況下樣式定義最近者爲準; 載入樣式以最後載入的定位爲準; 優先級爲: !important > id > class > tag important 比內聯優先級高,但內聯比 id 要高 補充:!important是css1中的(額,一直都不知道,還覺得是css3呢,慚愧啊。。。),因爲IE並不支持該語法,因此咱們能夠利用這一點解決部分CSS的瀏覽器兼容問題。 若是把的CSS樣式寫爲 a{color:teal !important;color:red} ,則在火狐和IE6+的瀏覽器裏則以color:teal爲準, 由於他們認識!important,則它的優化級高,因此採用color:teal。 而IE6呢,尤由它不認識!important,但能認識color:teal這個屬性,因此color:teal和color:red都要採用, 但後來定義的顏色會覆蓋 前面定義的顏色,也就是說color:red會覆蓋color:teal, 因此咱們在IE6裏我看到的應該是red這個色。 CSS3新增僞類舉例: p:first-of-type 選擇屬於其父元素的首個 <p> 元素的每一個 <p> 元素。 p:last-of-type 選擇屬於其父元素的最後 <p> 元素的每一個 <p> 元素。 p:only-of-type 選擇屬於其父元素惟一的 <p> 元素的每一個 <p> 元素。 p:only-child 選擇屬於其父元素的惟一子元素的每一個 <p> 元素。(父元素中只能有且只有一個p元素) p:nth-child(2) 選擇屬於其父元素的第二個子元素的每一個 <p> 元素。 :enabled :disabled 控制表單控件的禁用狀態。 :checked 單選框或複選框被選中。
CSS3實現圓角(border-radius),陰影(box-shadow), 對文字加特效(text-shadow、),線性漸變(gradient),旋轉(transform) transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);//旋轉,縮放,定位,傾斜 增長了更多的CSS選擇器 多背景 rgba 在CSS3中惟一引入的僞元素是::selection. 媒體查詢,多欄佈局 border-image
width: xx; //必定要設置寬度,不過但是設置爲相對值,則能夠實現自適應 text-overflow: ellipsis; white-space: nowrap; /*禁止自動換行*/ overflow: hidden;
區別:
1.全部的標記都必需要有一個相應的結束標記 2.全部標籤的元素和屬性的名字都必須使用小寫 3.全部的XML標記都必須合理嵌套 4.全部的屬性必須用引號""括起來 5.把全部<和&特殊符號用編碼表示 6.給全部屬性賦一個值 7.不要在註釋內容中使「--」 8.圖片必須有說明文字
4.常見的兼容性問題
png24位的圖片在iE6瀏覽器上出現背景,解決方案是作成PNG8.也能夠引用一段腳本處理. 瀏覽器默認的margin和padding不一樣。解決方案是加一個全局的*{margin:0;padding:0;}來統一。 IE6雙邊距bug:塊屬性標籤float後,又有橫行的margin狀況下,在ie6顯示margin比設置的大。 浮動ie產生的雙倍距離(IE6雙邊距問題:在IE6下,若是對元素設置了浮動,同時又設置了margin-left或margin-right,margin值會加倍。) #box{ float:left; width:10px; margin:0 0 0 100px;} 這種狀況之下IE會產生20px的距離,解決方案是在float的標籤樣式控制中加入 ——_display:inline;將其轉化爲行內屬性。(_這個符號只有ie6會識別) 漸進識別的方式,從整體中逐漸排除局部。 首先,巧妙的使用「\9」這一標記,將IE遊覽器從全部狀況中分離出來。 接着,再次使用「+」將IE8和IE七、IE6分離開來,這樣IE8已經獨立識別。 css .bb{ background-color:#f1ee18;/*全部識別*/ .background-color:#00deff\9; /*IE六、七、8識別*/ +background-color:#a200ff;/*IE六、7識別*/ _background-color:#1e0bd1;/*IE6識別*/ } IE下,能夠使用獲取常規屬性的方法來獲取自定義屬性,也能夠使用getAttribute()獲取自定義屬性; Firefox下,只能使用getAttribute()獲取自定義屬性. 解決方法:統一經過getAttribute()獲取自定義屬性. IE下,event對象有x,y屬性,可是沒有pageX,pageY屬性; Firefox下,event對象有pageX,pageY屬性,可是沒有x,y屬性. 解決方法:(條件註釋)缺點是在IE瀏覽器下可能會增長額外的HTTP請求數。 Chrome 中文界面下默認會將小於 12px 的文本強制按照 12px 顯示, 可經過加入 CSS 屬性 -webkit-text-size-adjust: none; 解決. 超連接訪問事後hover樣式就不出現了 被點擊訪問過的超連接樣式不在具備hover和active瞭解決方法是改變CSS屬性的排列順序: L-V-H-A : a:link {} a:visited {} a:hover
浮動元素脫離文檔流,不佔據空間。浮動元素碰到包含它的邊框或者浮動元素的邊框停留。 1.使用空標籤清除浮動。 這種方法是在全部浮動標籤後面添加一個空標籤 定義css clear:both. 弊端就是增長了無心義標籤。 2.使用overflow。 給包含浮動元素的父標籤添加css屬性 overflow:auto; zoom:1; zoom:1用於兼容IE6。 3.使用after僞對象清除浮動。 該方法只適用於非IE瀏覽器。具體寫法可參照如下示例。使用中需注意如下幾點。1、該方法中必須爲須要清除浮動元素的僞對象中設置 height:0,不然該元素會比實際高出若干像素;
浮動元素引發的問題: (1)父元素的高度沒法被撐開,影響與父元素同級的元素 (2)與浮動元素同級的非浮動元素會跟隨其後 (3)若非第一個元素浮動,則該元素以前的元素也須要浮動,不然會影響頁面顯示的結構 解決方法: 使用CSS中的clear:both;屬性來清除元素的浮動可解決二、3問題,對於問題1,添加以下樣式,給父元素添加clearfix樣式: .clearfix:after{content: ".";display: block;height: 0;clear: both;visibility: hidden;} .clearfix{display: inline-block;} /* for IE/Mac */
1,額外標籤法,<div style="clear:both;"></div>(缺點:不過這個辦法會增長額外的標籤使HTML結構看起來不夠簡潔。) 2,使用after僞類 #parent:after{ content:"."; height:0; visibility:hidden; display:block; clear:both; } 3,浮動外部元素 4,設置`overflow`爲`hidden`或者auto
線程是指進程內的一個執行單元,也是進程內的可調度實體. 與進程的區別: (1)地址空間:進程內的一個執行單元;進程至少有一個線程;它們共享進程的地址空間;而進程有本身獨立的地址空間; (2)資源擁有:進程是資源分配和擁有的單位,同一個進程內的線程共享進程的資源 (3)線程是處理器調度的基本單位,但進程不是. 4)兩者都可併發執行. 進程和線程都是由操做系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的併發性。進程和線程的區別在於: 簡而言之,一個程序至少有一個進程,一個進程至少有一個線程. 線程的劃分尺度小於進程,使得多線程程序的併發性高。 另外,進程在執行過程當中擁有獨立的內存單元,而多個線程共享內存,從而極大地提升了程序的運行效率。 線程在執行過程當中與進程仍是有區別的。每一個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。可是線程不可以獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。 從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分能夠同時執行。但操做系統並無將多個線程看作多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。 進程是具備必定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位. 線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程本身基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),可是它可與同屬一個進程的其餘的線程共享進程所擁有的所有資源. 一個線程能夠建立和撤銷另外一個線程;同一個進程中的多個線程之間能夠併發執行.
null是一個表示"無"的對象,轉爲數值時爲0;undefined是一個表示"無"的原始值,轉爲數值時爲NaN。 當聲明的變量還未被初始化時,變量的默認值爲undefined。 null用來表示還沒有存在的對象,經常使用來表示函數企圖返回一個不存在的對象。 undefined表示"缺乏值",就是此處應該有一個值,可是尚未定義。典型用法是: (1)變量被聲明瞭,但沒有賦值時,就等於undefined。 (2) 調用函數時,應該提供的參數沒有提供,該參數等於undefined。 (3)對象沒有賦值的屬性,該屬性的值爲undefined。 (4)函數沒有返回值時,默認返回undefined。 null表示"沒有對象",即該處不該該有值。典型用法是: (1) 做爲函數的參數,表示該函數的參數不是對象。 (2) 做爲對象原型鏈的終點。
補充一點:通常清除變量或方法,都是用的賦值爲null,js內存回收機制就會將其回收掉。html
分爲4個步驟: (1)當發送一個URL請求時,無論這個URL是Web頁面的URL仍是Web頁面上每一個資源的URL,瀏覽器都會開啓一個線程來處理這個請求,同時在遠程DNS服務器上啓動一個DNS查詢。這能使瀏覽器得到請求對應的IP地址。 (2)瀏覽器與遠程Web服務器經過TCP三次握手協商來創建一個TCP/IP鏈接。該握手包括一個同步報文,一個同步-應答報文和一個應答報文,這三個報文在 瀏覽器和服務器之間傳遞。該握手首先由客戶端嘗試創建起通訊,然後服務器應答並接受客戶端的請求,最後由客戶端發出該請求已經被接受的報文。 (3)一旦TCP/IP鏈接創建,瀏覽器會經過該鏈接向遠程服務器發送HTTP的GET請求。遠程服務器找到資源並使用HTTP響應返回該資源,值爲200的HTTP響應狀態表示一個正確的響應。 (4)此時,Web服務器提供資源服務,客戶端開始下載資源。 請求返回後,便進入了咱們關注的前端模塊
(1)建立XMLHttpRequest對象,也就是建立一個異步調用對象. (2)建立一個新的HTTP請求,並指定該HTTP請求的方法、URL及驗證信息. (3)設置響應HTTP請求狀態變化的函數. (4)發送HTTP請求. (5)獲取異步調用返回的數據. (6)使用JavaScript和DOM實現局部刷新.
//補充一個特別生動形象好記的方法前端
將ajax的實現過程比喻爲打電話 (1)首先得有一部電話吧 : 建立ajax對象 (2)撥通對方號碼: 鏈接到服務器 (3)說你要說的內容 : 發送請求(告訴服務器你要什麼) (4)聽對方的反饋 : 接收對方的響應
//具體的代碼實現html5
function ajax ( url , fnSucc ,fnFailed ) { //建立ajax對象 var oAjax = window.XMLHTTPRequest ? new XMLHTTPRequest() : new ActiveXObject("Microsoft.XMLHTTP"); //鏈接到服務器 oAjax.open("請求的類型" , "請求的內容", true); //最後一個爲是否爲異步 //發送請求 oAjax.send(); //接收響應 oAjax.onreaystatechange = function () { if ( oAjax.readyState == 4) { if ( oAjax.status == 200 ) { fnSucc(); } else { fnFailed(); } } } }
//readyState的5種值java
0 : (未初始化)尚未調用open()方法 1 : (載入)已調用send()方法,正在發送請求 2 : (載入完成)send()方法完成,已收到所有響應內容 3 : (解析)正在解析響應內容 4 : (完成)響應內容解析完成(不表明成功,成不成功還要看status的值),能夠在客戶端調用了
//status的值解析node
1xx表示臨時響應 100 (繼續) 請求者應當繼續提出請求。 服務器返回此代碼表示已收到請求的第一部分,正在等待其他部分。 101 (切換協議) 請求者已要求服務器切換協議,服務器已確認並準備切換。 2xx表示成功 200 (成功) 服務器已成功處理了請求。 一般,這表示服務器提供了請求的網頁。 201 (已建立) 請求成功而且服務器建立了新的資源。 202 (已接受) 服務器已接受請求,但還沒有處理。 203 (非受權信息) 服務器已成功處理了請求,但返回的信息可能來自另外一來源。 204 (無內容) 服務器成功處理了請求,但沒有返回任何內容。 205 (重置內容) 服務器成功處理了請求,但沒有返回任何內容。 206 (部份內容) 服務器成功處理了部分 GET 請求。 3xx重定向 300 (多種選擇) 針對請求,服務器可執行多種操做。 服務器可根據請求者 (user agent) 選擇一項操做,或提供操做列表供請求者選擇。 301 (永久移動) 請求的網頁已永久移動到新位置。 服務器返回此響應(對 GET 或 HEAD 請求的響應)時,會自動將請求者轉到新位置。 302 (臨時移動) 服務器目前從不一樣位置的網頁響應請求,但請求者應繼續使用原有位置來進行之後的請求。 303 (查看其餘位置) 請求者應當對不一樣的位置使用單獨的 GET 請求來檢索響應時,服務器返回此代碼。 304 (未修改) 自從上次請求後,請求的網頁未修改過。 服務器返回此響應時,不會返回網頁內容。 305 (使用代理) 請求者只能使用代理訪問請求的網頁。 若是服務器返回此響應,還表示請求者應使用代理。
306 在最新版的規範中,306狀態碼已經再也不被使用。 307 (臨時重定向) 服務器目前從不一樣位置的網頁響應請求,但請求者應繼續使用原有位置來進行之後的請求。 http狀態返回代碼 4xx(請求錯誤) 這些狀態代碼表示請求可能出錯,妨礙了服務器的處理。 4xx客戶端錯誤 400 (錯誤請求) 服務器不理解請求的語法。 401 (未受權) 請求要求身份驗證。 對於須要登陸的網頁,服務器可能返回此響應。 403 (禁止) 服務器拒絕請求。(剛纔騰訊面試的時候問到了。。。沒答出來) 404 (未找到) 服務器找不到請求的網頁。 405 (方法禁用) 禁用請求中指定的方法。 406 (不接受) 沒法使用請求的內容特性響應請求的網頁。 407 (須要代理受權) 此狀態代碼與 401(未受權)相似,但指定請求者應當受權使用代理。 408 (請求超時) 服務器等候請求時發生超時。 409 (衝突) 服務器在完成請求時發生衝突。 服務器必須在響應中包含有關衝突的信息。 410 (已刪除) 若是請求的資源已永久刪除,服務器就會返回此響應。 411 (須要有效長度) 服務器不接受不含有效內容長度標頭字段的請求。 412 (未知足前提條件) 服務器未知足請求者在請求中設置的其中一個前提條件。 413 (請求實體過大) 服務器沒法處理請求,由於請求實體過大,超出服務器的處理能力。 414 (請求的 URI 過長) 請求的 URI(一般爲網址)過長,服務器沒法處理。 415 (不支持的媒體類型) 請求的格式不受請求頁面的支持。 416 (請求範圍不符合要求) 若是頁面沒法提供請求的範圍,則服務器會返回此狀態代碼。 417 (未知足指望值) 服務器未知足"指望"請求標頭字段的要求。 5xx服務器端錯誤 500 (服務器內部錯誤) 服務器遇到錯誤,沒法完成請求。 501 (還沒有實施) 服務器不具有完成請求的功能。 例如,服務器沒法識別請求方法時可能會返回此代碼。 502 (錯誤網關) 服務器做爲網關或代理,從上游服務器收到無效響應。 503 (服務不可用) 服務器目前沒法使用(因爲超載或停機維護)。 一般,這只是暫時狀態。 504 (網關超時) 服務器做爲網關或代理,可是沒有及時從上游服務器收到請求。 505 (HTTP 版本不受支持) 服務器不支持請求中所用的 HTTP 協議版本。
一、建立一個空對象,而且 this 變量引用該對象,同時還繼承了該函數的原型。 二、屬性和方法被加入到 this 引用的對象中。 三、新建立的對象由 this 所引用,而且最後隱式的返回 this 。 var obj = {}; obj.__proto__ = Base.prototype; Base.call(obj);
document.write只能重繪整個頁面
innerHTML能夠重繪頁面的一部分
內存泄漏指任何對象在您再也不擁有或須要它以後仍然存在。 垃圾回收器按期掃描對象,並計算引用了每一個對象的其餘對象的數量。若是一個對象的引用數量爲 0(沒有其餘對象引用過該對象),或對該對象的唯一引用是循環的,那麼該對象的內存便可回收。 setTimeout 的第一個參數使用字符非串而函數的話,會引起內存泄漏。
閉包、控制檯日誌、循環(在兩個對象彼此引用且彼此保留時,就會產生一個循環)
Doctype做用? 嚴格模式與混雜模式如何區分?它們有何意義? (1)<!DOCTYPE> 聲明位於文檔中的最前面,處於 <html> 標籤以前。告知瀏覽器以何種模式來渲染文檔。 (2)嚴格模式的排版和 JS 運做模式是 以該瀏覽器支持的最高標準運行。 (3)在混雜模式中,頁面以寬鬆的向後兼容的方式顯示。模擬老式瀏覽器的行爲以防止站點沒法工做。 (4)DOCTYPE不存在或格式不正確會致使文檔以混雜模式呈現。
你知道多少種Doctype文檔類型? 該標籤可聲明三種 DTD 類型,分別表示嚴格版本、過渡版本以及基於框架的 HTML 文檔。 HTML 4.01 規定了三種文檔類型:Strict、Transitional 以及 Frameset。 XHTML 1.0 規定了三種 XML 文檔類型:Strict、Transitional 以及 Frameset。 Standards (標準)模式(也就是嚴格呈現模式)用於呈現遵循最新標準的網頁,而 Quirks (包容)模式(也就是鬆散呈現模式或者兼容模式)用於呈現爲傳統瀏覽器而設計的網頁。
cookie雖然在持久保存客戶端數據提供了方便,分擔了服務器存儲的負擔,但仍是有不少侷限性的。 第一:每一個特定的域名下最多生成20個cookie 1.IE6或更低版本最多20個cookie 2.IE7和以後的版本最後能夠有50個cookie。 3.Firefox最多50個cookie 4.chrome和Safari沒有作硬性限制 IE和Opera 會清理近期最少使用的cookie,Firefox會隨機清理cookie。 cookie的最大大約爲4096字節,爲了兼容性,通常不能超過4095字節。 IE 提供了一種存儲能夠持久化用戶數據,叫作userData,從IE5.0就開始支持。每一個數據最多128K,每一個域名下最多1M。這個持久化數據放在緩存中,若是緩存沒有清理,那麼會一直存在。 優勢:極高的擴展性和可用性 1.經過良好的編程,控制保存在cookie中的session對象的大小。 2.經過加密和安全傳輸技術(SSL),減小cookie被破解的可能性。 3.只在cookie中存放不敏感數據,即便被盜也不會有重大損失。 4.控制cookie的生命期,使之不會永遠有效。偷盜者極可能拿到一個過時的cookie。
缺點: 1.`Cookie`數量和長度的限制。每一個domain最多隻能有20條cookie,每一個cookie長度不能超過4KB,不然會被截掉。 2.安全性問題。若是cookie被人攔截了,那人就能夠取得全部的session信息。即便加密也與事無補,由於攔截者並不須要知道cookie的意義,他只要原樣轉發cookie就能夠達到目的了。 3.有些狀態不可能保存在客戶端。例如,爲了防止重複提交表單,咱們須要在服務器端保存一個計數器。若是咱們把這個計數器保存在客戶端,那麼它起不到任何做用。
在較高版本的瀏覽器中,js提供了sessionStorage和globalStorage。在HTML5中提供了localStorage來取代globalStorage。
html5中的Web Storage包括了兩種存儲方式:sessionStorage和localStorage。
sessionStorage用於本地存儲一個會話(session)中的數據,這些數據只有在同一個會話中的頁面才能訪問而且當會話結束後數據也隨之銷燬。所以sessionStorage不是一種持久化的本地存儲,僅僅是會話級別的存儲。
而localStorage用於持久化的本地存儲,除非主動刪除數據,不然數據是永遠不會過時的。
Cookie: 在web中獲得普遍應用,但侷限性很是明顯,容量過小,有些站點會由於出於安全的考慮而禁用cookie,cookie沒有想象中的那麼安全,Cookie 的內容會隨着頁面請求一併發往服務器。
User Data: 是微軟爲IE專門在系統中開闢的一塊存儲空間,因此說只支持Windows+IE的組合,實際測試在2000(IE5.5)、XP(IE六、IE7),Vista(IE7)下都是能夠正常使用的。在XP下,通常位於C:\Documents and Settings\用戶名\UserData,有些時候會在C:\Documents and Settings\用戶名\Application Data\Microsoft\Internet Explorer\UserData。在Vista下,位於C:\Users\用戶名\AppData\Roaming\Microsoft\Internet Explorer\UserData;單個文件的大小限制是128KB,一個域名下總共能夠保存1024KB的文件,文件個數應該沒有限制。在受限站點裏這兩個值分別是64KB和640KB,因此若是考慮到各類狀況的話,單個文件最好能控制64KB如下。
相對於上述本地存儲方案,localStorage有自身的優勢:容量大、易用、強大、原生支持;缺點是兼容性差些(chrome, safari, firefox,IE 9,IE8都支持 localStorage,主要是IE8如下版本不支持)、安全性也差些(因此請勿使用localStorage保存敏感信息)。
Web Storage的概念和cookie類似,區別是它是爲了更大容量存儲設計的。Cookie的大小是受限的,而且每次你請求一個新的頁面的時候Cookie都會被髮送過去,這樣無形中浪費了帶寬,另外cookie還須要指定做用域,不能夠跨域調用。
除此以外,Web Storage擁有setItem,getItem,removeItem,clear等方法,不像cookie須要前端開發者本身封裝setCookie,getCookie。
可是Cookie也是不能夠或缺的:Cookie的做用是與服務器進行交互,做爲HTTP規範的一部分而存在 ,而Web Storage僅僅是爲了在本地「存儲」數據而生
瀏覽器的支持除了IE7及如下不支持外,其餘標準瀏覽器都徹底支持(ie及FF需在web服務器裏運行),值得一提的是IE老是辦好事,例如IE七、IE6中的UserData其實就是javascript本地存儲的解決方案。經過簡單的代碼封裝能夠統一到全部的瀏覽器都支持web storage。
localStorage和sessionStorage都具備相同的操做方法,例如setItem、getItem和removeItem等
1.不要在同一行聲明多個變量。 2.請使用 ===/!== 來比較true/false或者數值 (好吧,這一條我總是用== 和 != 去比較,可是=== 是要求類型和值都要徹底相等的全等,要求很嚴格,通常我比較str和number都會現將其類型強制轉換爲int) 3.使用對象字面量替代new Array這種形式
4.不要使用全局函數。 5.Switch語句必須帶有default分支 6.函數不該該有時候有返回值,有時候沒有返回值。 7.For循環必須使用大括號 8.If語句必須使用大括號 9.for-in循環中的變量 應該使用var關鍵字明確限定做用域,從而避免做用域污染。
//這裏補充一個什麼是對象字面量: 形式是:{鍵:值,鍵:值}
語法中的「健/值」會成爲對象的靜態成員。
若是給某個「健」指定的值是一個匿名函數,那麼該函數就會變成對象的靜態方法;不然就是對象的一個靜態屬性。
這種語法結構與JSON語法類似。只要記住對象字面量語法會自動建立Object對象實例便可,也就是不能使用new關鍵字對其再次進行實例化。
http://www.cnblogs.com/TomXu/archive/2011/12/28/2286877.html
它的功能是把對應的字符串解析成JS代碼並運行;
應該避免使用eval,不安全,很是耗性能(2次,一次解析成js語句,一次執行)。
var json = eval('(' + str + ')');
()是一個 分組運算符. 做用是優先級. 本質就是捨棄其餘可能的多餘的語法樹. 之因此要這樣作的緣由是 {} 花括號二義性形成的. eval('{a:1}') //不會拋出異常. 結果是1 eval('{a:1,b:2}') //拋出異常 : Uncaught SyntaxError: Unexpected token :
對比:
eval('({a:1})'); //Object {a:1}
eval('({a:1,b:2})'); //Object{a:1,b:2}
這並非eval的錯. 錯誤來自語法分析時, {}被當作 statement block(語句塊),而不是一個 JSONObject(Json對象). 因此.拋出異常是由於a:1被解析成 lableStatement(標籤聲明) 了.那麼它後面的 "," 逗號,就使得parser不得不停下來了.由於 逗號運算符不能出如今lableStatement後面. 因此 { a:1, b:2 } 在任何被解析爲statement block的狀況下.都將致使異常. 解決辦法.把他們併入表達式.讓parser使用 JSONObject的語法樹.好比 ({a:1,b:2}) 1,{a:1,b:2} +{a:1,b:2} var a ={a:1,b:2} 等等等等... 說說爲何()不是強制運算符,由於它不具有這個功能. 分組運算符 同 delete typeof 等運算符相似. 不會對運算元.形成 GetValue() . 舉個例子: delete 玩笑; //不會拋出異常. 緣由是運行時,執行到 delete 玩笑; 時, 並不會對標識符-玩笑,進行GetValue(). delete (玩笑);//一樣不會拋出異常. 可見分組運算符() 並無對 標識符 -玩笑 作額外的工做. 它僅僅是影響語法樹的產生過程. 從ECMA262的角度來看此問題亦如此. 這裏涉及到 Reference Type 的base property 爲null時的狀況下,對其 GetValue()才拋出異常.
(1) defer,只支持IE (2) async: (3) 建立script,插入到DOM中,加載完畢後callBack
//補充一些,感受這個蠻重要的,摘自:http://blog.csdn.net/m13666368773/article/details/7586106jquery
1. 同步加載 咱們平時最常使用的就是這種同步加載形式: <script src="http://yourdomain.com/script.js"></script> 同步模式,又稱阻塞模式,會阻止瀏覽器的後續處理,中止了後續的解析,所以中止了後續的文件加載(如圖像)、渲染、代碼執行。 js 之因此要同步執行,是由於 js 中可能有輸出 document 內容、修改dom、重定向等行爲,因此默認同步執行纔是安全的。 之前的通常建議是把<script>放在頁面末尾</body>以前,這樣儘量減小這種阻塞行爲,而先讓頁面展現出來。 簡單說:加載的網絡 timeline 是瀑布模型,而異步加載的 timeline 是併發模型。
2. 常見異步加載(Script DOM Element)
(function() { var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'http://yourdomain.com/script.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); })();
可是,這種加載方式在加載執行完以前會阻止 onload 事件的觸發,而如今不少頁面的代碼都在 onload 時還要執行額外的渲染工做等,因此仍是會阻塞部分頁面的初始化處理。
3. onload 時的異步加載
(function() {
function async_load(){ var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'http://yourdomain.com/script.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); } if (window.attachEvent) window.attachEvent('onload', async_load); else window.addEventListener('load', async_load, false); })();
這和前面的方式差很少,但關鍵是它不是當即開始異步加載 js ,而是在 onload 時纔開始異步加載。這樣就解決了阻塞 onload 事件觸發的問題。
var xhrObj = getXHRObject(); xhrObj.onreadystatechange = function() { if ( xhrObj.readyState != 4 ) return; eval(xhrObj.responseText); }; xhrObj.open('GET', 'A.js', true); xhrObj.send('');
var iframe = document.createElement('iframe'); document.body.appendChild(iframe); var doc = iframe.contentWindow.document; doc.open().write('<body onload="insertJS()">'); doc.close();
<script type="text/javascript"> /* var ... */ </script>
2、async 和 defer 屬性
<script src="file.js" defer></script>
<script src="file.js" async></script>
Both async and defer scripts begin to download immediately without pausing the parser and both support an optional onload handler to address the common need to perform initialization which depends on the script. The difference between async and defer centers around when the script is executed. Each async script executes at the first opportunity after it is finished downloading and before the window’s load event. This means it’s possible (and likely) thatasync scripts are not executed in the order in which they occur in the page. The defer scripts, on the other hand, are guaranteed to be executed in the order they occur in the page. That execution starts after parsing is completely finished, but before the document’sDOMContentLoaded event.
注:其實翻譯過來指的就是async和defer最大的區別在於下載完腳本之後何時執行。每一個async(異步)腳本都是在下載完後儘快執行,因此不能保證腳本會按順序執行。而defer腳本(延遲腳本)則保證按照順序執行的。css3
另 :
說明:
沒有 async 屬性,script 將當即獲取(下載)並執行,而後才繼續後面的處理,這期間阻塞了瀏覽器的後續處理。
若是有 async 屬性,那麼 script 將被異步下載並執行,同時瀏覽器繼續後續的處理。
HTML4中就有了defer屬性,它提示瀏覽器這個 script 不會產生任何文檔元素(沒有document.write),所以瀏覽器會繼續後續處理和渲染。
若是沒有 async 屬性 可是有 defer 屬性,那麼script 將在頁面parse以後執行。
若是同時設置了兩者,那麼 defer 屬性主要是爲了讓不支持 async 屬性的老瀏覽器按照原來的 defer 方式處理,而不是同步方式。
延遲加載:有些 js 代碼並非頁面初始化的時候就馬上須要的,而稍後的某些狀況才須要的。延遲加載就是一開始並不加載這些暫時不用的js,而是在須要的時候或稍後再經過js 的控制來異步加載。
也就是將 js 切分紅許多模塊,頁面初始化時只加載須要當即執行的 js ,而後其它 js 的加載延遲到第一次須要用到的時候再加載。
特別是頁面有大量不一樣的模塊組成,不少可能暫時不用或根本就沒用到。
就像圖片的延遲加載,在圖片出如今可視區域內時(在滾動條下拉)才加載顯示圖片。
1. script 放在 HEAD 中 <head> <script src=「…」></script> </head> 阻止了後續的下載; 在IE 6-7 中 script 是順序下載的,而不是如今的 「並行下載、順序執行」 的方式; 在下載和解析執行階段阻止渲染(rendering); 2. script 放在頁面底部(2007) ... <script src=「…」></script> </body> 不阻止其它下載; 在IE 6-7 中 script 是順序下載的; 在下載和解析執行階段阻止渲染(rendering);
3. 異步加載script(2009) var se = document.createElement ('script'); se.src = 'http://anydomain.com/A.js'; document.getElementsByTagName('head') [0].appendChild(se); 不阻止其它下載; 在全部瀏覽器中,script都是並行下載; 只在解析執行階段阻止渲染(rendering);
4. 異步下載 + 按需執行 (2010) var se = new Image(); se.onload = registerScript(); se.src = 'http://anydomain.com/A.js'; 把下載 js 與 解析執行 js 分離出來 不阻止其它下載; 在全部瀏覽器中,script都是並行下載; 不阻止渲染(rendering)直到真正須要時;
pushState()方法 pushState()有三個參數:一個狀態對象、一個標題(如今會被忽略),一個可選的URL地址。下面來單獨考察這三個參數的細節: 狀態對象(state object) — 一個JavaScript對象,與用pushState()方法建立的新歷史記錄條目關聯。不管什麼時候用戶導航到新建立的狀態,popstate事件都會被觸發,而且事件對象的state屬性都包含歷史記錄條目的狀態對象的拷貝。 任何可序列化的對象均可以被當作狀態對象。由於FireFox瀏覽器會把狀態對象保存到用戶的硬盤,這樣它們就能在用戶重啓瀏覽器以後被還原,咱們強行限制狀態對象的大小爲640k。若是你向pushState()方法傳遞了一個超過該限額的狀態對象,該方法會拋出異常。若是你須要存儲很大的數據,建議使用sessionStorage或localStorage。 標題(title) — FireFox瀏覽器目前會忽略該參數,雖然之後可能會用上。考慮到將來可能會對該方法進行修改,傳一個空字符串會比較安全。或者,你也能夠傳入一個簡短的標題,標明將要進入的狀態。 地址(URL) — 新的歷史記錄條目的地址。瀏覽器不會在調用pushState()方法後加載該地址,但以後,可能會試圖加載,例如用戶重啓瀏覽器。新的URL不必定是絕對路徑;若是是相對路徑,它將以當前URL爲基準;傳入的URL與當前URL應該是同源的,不然,pushState()會拋出異常。該參數是可選的;不指定的話則爲文檔當前URL。 注意: 在 Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) 至 Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2) 中,傳入的對象使用JSON來進行序列化。從 Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)開始,對象使用結構化拷貝算法來進行序列化。這將容許更多類型的對象可以安全傳入。
某種意義上,調用pushState()有點相似於設置window.location='#foo',它們都會在當前文檔內建立和激活新的歷史記錄條目。但pushState()有本身的優點:
新的URL能夠是任意的同源URL,與此相反,使用window.location方法時,只有僅修改 hash 才能保證停留在相同的document中。 根據我的須要來決定是否修改URL。相反,設置window.location='#foo',只有在當前hash值不是foo時才建立一條新歷史記錄。 你能夠在新的歷史記錄條目中添加抽象數據。若是使用基於hash的方法,你只能把相關數據轉碼成一個很短的字符串。 注意pushState()方法永遠不會觸發hashchange事件,即使新的地址只變動了hash。 replaceState()方法 history.replaceState()操做相似於history.pushState(),不一樣之處在於replaceState()方法會修改當前歷史記錄條目而並不是建立新的條目。 當你爲了響應用戶的某些操做,而要更新當前歷史記錄條目的狀態對象或URL時,使用replaceState()方法會特別合適。
URL:http://b.a.com:88/index.php?name=kang&when=2011#first protocol: 協議 "http:" hostname: 服務器的名字 "b.a.com" port: 端口 "88" pathname: URL中主機名後的部分 "/index.php" search: "?"後的部分,又稱爲查詢字符串 "?name=kang&when=2011" hash: 返回"#"以後的內容 "#first" host: 等於hostname + port "b.a.com:88" href: 當前頁面的完整URL "http://www.a.com:88/index.php?name=kang&when=2011#first"
概念:同源策略是客戶端腳本(尤爲是Javascript)的重要的安全度量標準。它最先出自Netscape Navigator2.0,其目的是防止某個文檔或腳本從多個不一樣源裝載。
這裏的同源策略指的是:協議,域名,端口相同,同源策略是一種安全協議。
指一段腳本只能讀取來自同一來源的窗口和文檔的屬性。
爲何要有同源限制?
咱們舉例說明:好比一個黑客程序,他利用Iframe把真正的銀行登陸頁面嵌到他的頁面上,當你使用真實的用戶名,密碼登陸時,他的頁面就能夠經過Javascript讀取到你的表單中input中的內容,這樣用戶名,密碼就輕鬆到手了。
那麼接下來的問題就是跨域問題啦??
答案:http://www.cnblogs.com/shixiaomiao/p/4758434.html
GET:通常用於信息獲取,使用URL傳遞參數,對所發送信息的數量也有限制,通常在2000個字符
POST:通常用於修改服務器上的資源,對所發送的信息沒有限制。
GET方式須要使用Request.QueryString來取得變量的值,而POST方式經過Request.Form來獲取變量的值,
也就是說Get是經過地址欄來傳值,而Post是經過提交表單來傳值。
然而,在如下狀況中,請使用 POST 請求:
沒法使用緩存文件(更新服務器上的文件或數據庫)
向服務器發送大量數據(POST 沒有數據量限制)
發送包含未知字符的用戶輸入時,POST 比 GET 更穩定也更可靠
總結:
GET: 容量小,安全性差(經過網址傳遞),有緩存
POST : 容量大(2G),安全性較好點,沒有緩存
//補充,ajax的type有幾種
默認值: "GET")。請求方式 ("POST" 或 "GET"), 默認爲 "GET"。注意:其它 HTTP 請求方法,如 PUT 和 DELETE 也能夠使用,但僅部分瀏覽器支持。
其實這四種方式對應的就是: 數據庫操做的 增(PUT),刪(DELETE),改(POST),查(GET)
//反正都寫了,那就把jquery中的ajax參數都列一下
參數 options 類型:Object 可選。AJAX 請求設置。全部選項都是可選的。 async 類型:Boolean 默認值: true。默認設置下,全部請求均爲異步請求。若是須要發送同步請求,請將此選項設置爲 false。 注意,同步請求將鎖住瀏覽器,用戶其它操做必須等待請求完成才能夠執行。
beforeSend(XHR) 類型:Function 發送請求前可修改 XMLHttpRequest 對象的函數,如添加自定義 HTTP 頭。
XMLHttpRequest 對象是惟一的參數。 這是一個 Ajax 事件。若是返回 false 能夠取消本次 ajax 請求。
cache 類型:Boolean 默認值: true,dataType 爲 script 和 jsonp 時默認爲 false。設置爲 false 將不緩存此頁面。 jQuery 1.2 新功能。
complete(XHR, TS) 類型:Function 請求完成後回調函數 (請求成功或失敗以後均調用)。 參數: XMLHttpRequest 對象和一個描述請求類型的字符串。 這是一個 Ajax 事件。
contentType 類型:String 默認值: "application/x-www-form-urlencoded"。發送信息至服務器時內容編碼類型。 默認值適合大多數狀況。若是你明確地傳遞了一個 content-type 給 $.ajax() 那麼它一定會發送給服務器(即便沒有數據要發送)。
context 類型:Object 這個對象用於設置 Ajax 相關回調函數的上下文。也就是說,讓回調函數內 this 指向這個對象(若是不設定這個參數,那麼 this 就指向調用本次 AJAX 請求時傳遞的 options 參數)。好比指定一個 DOM 元素做爲 context 參數,這樣就設置了 success 回調函數的上下文爲這個 DOM 元素。 就像這樣: $.ajax({ url: "test.html", context: document.body, success: function(){ $(this).addClass("done"); }});
data 類型:String 發送到服務器的數據。將自動轉換爲請求字符串格式。
GET 請求中將附加在 URL 後。查看 processData 選項說明以禁止此自動轉換。
必須爲 Key/Value 格式。
若是爲數組,jQuery 將自動爲不一樣值對應同一個名稱。
如 {foo:["bar1", "bar2"]} 轉換爲 '&foo=bar1&foo=bar2'。
dataFilter 類型:Function 給 Ajax 返回的原始數據的進行預處理的函數。提供 data 和 type 兩個參數:data 是 Ajax 返回的原始數據,type 是調用 jQuery.ajax 時提供的 dataType 參數。函數返回的值將由 jQuery 進一步處理。
dataType 類型:String 預期服務器返回的數據類型。若是不指定,jQuery 將自動根據 HTTP 包 MIME 信息來智能判斷,好比 XML MIME 類型就被識別爲 XML。在 1.4 中,JSON 就會生成一個 JavaScript 對象,而 script 則會執行這個腳本。
隨後服務器端返回的數據會根據這個值解析後,傳遞給回調函數。
可用值: "xml": 返回 XML 文檔,可用 jQuery 處理。 "html": 返回純文本 HTML 信息;包含的 script 標籤會在插入 dom 時執行。 "script": 返回純文本 JavaScript 代碼。不會自動緩存結果。除非設置了 "cache" 參數。注意:在遠程請求時(不在同一個域下),全部 POST 請求都將轉爲 GET 請求。(由於將使用 DOM 的 script標籤來加載) "json": 返回 JSON 數據 。 "jsonp": JSONP 格式。使用 JSONP 形式調用函數時,如 "myurl?callback=?" jQuery 將自動替換 ? 爲正確的函數名,以執行回調函數。 "text": 返回純文本字符串
error 類型:Function 默認值: 自動判斷 (xml 或 html)。請求失敗時調用此函數。 有如下三個參數:XMLHttpRequest 對象、錯誤信息、(可選)捕獲的異常對象。 若是發生了錯誤,錯誤信息(第二個參數)除了獲得 null 以外,還多是 "timeout", "error", "notmodified" 和 "parsererror"。 這是一個 Ajax 事件。
global 類型:Boolean 是否觸發全局 AJAX 事件。默認值: true。設置爲 false 將不會觸發全局 AJAX 事件,如 ajaxStart 或 ajaxStop 可用於控制不一樣的 Ajax 事件。
ifModified 類型:Boolean 僅在服務器數據改變時獲取新數據。默認值: false。使用 HTTP 包 Last-Modified 頭信息判斷。在 jQuery 1.4 中,它也會檢查服務器指定的 'etag' 來肯定數據沒有被修改過。
jsonp 類型:String 在一個 jsonp 請求中重寫回調函數的名字。這個值用來替代在 "callback=?" 這種 GET 或 POST 請求中 URL 參數裏的 "callback" 部分,好比 {jsonp:'onJsonPLoad'} 會致使將 "onJsonPLoad=?" 傳給服務器。
jsonpCallback 類型:String 爲 jsonp 請求指定一個回調函數名。這個值將用來取代 jQuery 自動生成的隨機函數名。這主要用來讓 jQuery 生成度獨特的函數名,這樣管理請求更容易,也能方便地提供回調函數和錯誤處理。你也能夠在想讓瀏覽器緩存 GET 請求的時候,指定這個回調函數名。
password 類型:String 用於響應 HTTP 訪問認證請求的密碼
processData 類型:Boolean 默認值: true。默認狀況下,經過data選項傳遞進來的數據,若是是一個對象(技術上講只要不是字符串),都會處理轉化成一個查詢字符串,以配合默認內容類型 "application/x-www-form-urlencoded"。若是要發送 DOM 樹信息或其它不但願轉換的信息,請設置爲 false。
scriptCharset 類型:String 只有當請求時 dataType 爲 "jsonp" 或 "script",而且 type 是 "GET" 纔會用於強制修改 charset。一般只在本地和遠程的內容編碼不一樣時使用。
success 類型:Function 請求成功後的回調函數。 參數:由服務器返回,並根據 dataType 參數進行處理後的數據;描述狀態的字符串。 這是一個 Ajax 事件。
traditional 類型:Boolean 若是你想要用傳統的方式來序列化數據,那麼就設置爲 true。請參考工具分類下面的 jQuery.param 方法。
timeout 類型:Number 設置請求超時時間(毫秒)。此設置將覆蓋全局設置。
type 類型:String 默認值: "GET")。請求方式 ("POST" 或 "GET"), 默認爲 "GET"。注意:其它 HTTP 請求方法,如 PUT 和 DELETE 也能夠使用,但僅部分瀏覽器支持。
url 類型:String 默認值: 當前頁地址。發送請求的地址。
username 類型:String 用於響應 HTTP 訪問認證請求的用戶名。
xhr 類型:Function 須要返回一個 XMLHttpRequest 對象。默認在 IE 下是 ActiveXObject 而其餘狀況下是 XMLHttpRequest 。用於重寫或者提供一個加強的 XMLHttpRequest 對象。這個參數在 jQuery 1.3 之前不可用。
回調函數 若是要處理 $.ajax() 獲得的數據,則須要使用回調函數:beforeSend、error、dataFilter、success、complete。
beforeSend 在發送請求以前調用,而且傳入一個 XMLHttpRequest 做爲參數。
error 在請求出錯時調用。傳入 XMLHttpRequest 對象,描述錯誤類型的字符串以及一個異常對象(若是有的話)
dataFilter 在請求成功以後調用。傳入返回的數據以及 "dataType" 參數的值。而且必須返回新的數據(多是處理過的)傳遞給 success 回調函數。
success 當請求以後調用。傳入返回後的數據,以及包含成功代碼的字符串。
complete 當請求完成以後調用這個函數,不管成功或失敗。傳入 XMLHttpRequest 對象,以及一個包含成功或錯誤代碼的字符串。
js的阻塞特性:全部瀏覽器在下載JS的時候,會阻止一切其餘活動,好比其餘資源的下載,內容的呈現等等。直到JS下載、解析、執行完畢後纔開始繼續並行下載其餘資源並呈現內容。
爲了提升用戶體驗,新一代瀏覽器都支持並行下載JS,可是JS下載仍然會阻塞其它資源的下載(例如.圖片,css文件等)。
因爲瀏覽器爲了防止出現JS修改DOM樹,須要從新構建DOM樹的狀況,因此就會阻塞其餘的下載和呈現。
嵌入JS會阻塞全部內容的呈現,而外部JS只會阻塞其後內容的顯示,2種方式都會阻塞其後資源的下載。也就是說外部樣式不會阻塞外部腳本的加載,但會阻塞外部腳本的執行。
CSS怎麼會阻塞加載了?CSS原本是能夠並行下載的,在什麼狀況下會出現阻塞加載了(在測試觀察中,IE6下CSS都是阻塞加載)
當CSS後面跟着嵌入的JS的時候,該CSS就會出現阻塞後面資源下載的狀況。而當把嵌入JS放到CSS前面,就不會出現阻塞的狀況了。
根本緣由:由於瀏覽器會維持html中css和js的順序,樣式表必須在嵌入的JS執行前先加載、解析完。而嵌入的JS會阻塞後面的資源加載,因此就會出現上面CSS阻塞下載的狀況。
當瀏覽器從服務器接收到了HTML文檔,並把HTML在內存中轉換成DOM樹,在轉換的過程當中若是發現某個節點(node)上引用了CSS或者IMAGE,就會再發1個request去請求CSS或image,而後繼續執行下面的轉換,而不須要等待request的返回,當request返回後,只須要把返回的內容放入到DOM樹中對應的位置就OK。
但當引用了JS的時候,瀏覽器發送1個js request就會一直等待該request的返回。由於瀏覽器須要1個穩定的DOM樹結構,而JS中頗有可能有代碼直接改變了DOM樹結構,好比使用document.write 或 appendChild,甚至是直接使用的location.href進行跳轉,瀏覽器爲了防止出現JS修改DOM樹,須要從新構建DOM樹的狀況,因此就會阻塞其餘的下載和呈現.
總結:上下文其實就是找準對象,做用域就是能夠使用的邊界(能夠發生做用的邊界)
首先須要澄清的問題是上下文和做用域是不一樣的概念。 每一個函數調用都有與之相關的做用域和上下文。從根本上說,範圍是基於函數(function-based)而上下文是基於對象(object-based)。換句話說,做用域是和每次函數調用時變量的訪問有關,而且每次調用都是獨立的。上下文老是關鍵字 this 的值,是調用當前可執行代碼的對象的引用。
變量做用域
變量可以被定義在局部或者全局做用域,這致使運行時變量的訪問來自不一樣的做用域。全局變量需被聲明在函數體外,在整個運行過程當中都存在,能在任何做用域中訪問和修改。局部變量僅在函數體內定義,而且每次函數調用都有不一樣的做用域。這主題是僅在調用中的賦值,求值和對值的操做,不能訪問做用域以外的值。
目前javascript不支持塊級做用域,塊級做用域指在if語句,switch語句,循環語句等語句塊中定義變量,這意味着變量不能在語句塊以外被訪問。當前任何在語句塊中定義的變量都能在語句塊以外訪問。然而,這種狀況很快會獲得改變,let 關鍵字已經正式添加到ES6規範。用它來代替var關鍵字能夠將局部變量聲明爲塊級做用域。
"this" 上下文
上下文一般是取決於一個函數如何被調用。當函數做爲對象的方法被調用時,this 被設置爲調用方法的對象:
var object = {
foo: function(){
console.log(this === object);
}
};
object.foo(); // true
一樣的原理適用於當調用一個函數時經過new的操做符建立一個對象的實例。當以這種方式調用時,this 的值將被設置爲新建立的實例:
function foo(){
console.log(this);
}
foo() // window對象
new foo() // foo {}對象
當調用一個未綁定函數,this 將被默認設置爲 全局上下文(global context) 或window對象(若是在瀏覽器中)。然而若是函數在嚴格模式下被執行("use strict"),this的值將被默認設置爲undefined。
javascript是一個單線程語言,這意味着在瀏覽器中同時只能作一件事情。當javascript解釋器初始執行代碼,它首先默認全局上下文。每次調用一個函數將會建立一個新的執行上下文(注:執行上下文(execution context)「在這裏的所要表達的意思是做用域)。
每次新建立一個執行上下文(注:此處指的是做用域),會被添加到做用域鏈的頂部,又是也成爲執行或調用棧。瀏覽器老是運行在位於做用域鏈頂部當前執行上下文。一旦完成,它(當前執行上下文)將從棧頂被移除而且將控制權歸還給以前的執行上下文。
不一樣執行上下文之間的變量命名衝突經過攀爬做用域鏈解決,從局部直到全局。這意味着具備相同名稱的局部變量在做用域鏈中有更高的優先級。 (近水樓臺先得月)
簡單的說,每次你試圖訪問函數執行上下文中的變量時,查找進程老是從本身的變量對象開始。若是在本身的變量對象中沒發現要查找的變量,繼續搜索做用域鏈。它將攀爬做用域鏈檢查每個執行上下文的變量對象去尋找和變量名稱匹配的值。(這個能夠理解爲就近原則)
最流行的閉包類型是廣爲人知的模塊模式。它容許你模擬公共的,私有的和特權成員:
var Module = (function(){
var privateProperty = 'foo';
function privateMethod(args){
//do something
}
return {
publicProperty: "",
publicMethod: function(args){
//do something
}
}
})();
//此時的Module對象在外部只能獲取到的是publicProperty屬性和publicMethod方法。
模塊實際上有些相似於單例,在末尾添加一對括號,當解釋器解釋完後當即執行(當即執行函數)。閉包執行上下位的外部惟一可用的成員是返回對象中公用的方法和屬性(例如Module.publicMethod)。然而,全部的私有屬性和方法在整個程序的生命週期中都將存在,因爲(閉包)使執行上下文收到保護,和變量的交互要經過公用的方法。(其實所謂的公有和私有,就是看有沒有return出去啦)
另外一種類型的閉包叫作當即調用函數表達式(immediately-invoked function expression IIFE),無非是一個在window上下文中的自調用匿名函數(self-invoked anonymous function)。
function(window){
var a = 'foo', b = 'bar';
function private(){
// do something
}
window.Module = {
public: function(){
// do something
}
};
})(this);
對保護全局命名空間,這種表達式很是有用,全部在函數體內聲明的變量都是局部變量,並經過閉包在整個運行環境保持存在。這種封裝源代碼的方式對程序和框架都是很是流行的,一般暴露單一全局接口與外界交互。
call和apply的區別講得最多的就是,傳入參數的形式的不一樣 apply只接受兩個參數 eg: user.call(window, 'John', 'Doe', 30); user.apply(window, ['John', 'Doe', 30]); (其實還記得其餘地方有講二者還有其餘的不一樣,找不到了。。。等之後發現了,再來補)
至於這個bind之前沒怎麼太關注過啊!
先引用一下大牛們的話
Jack Archibald 關於緩存 this 的微博(twitter): Jake Archibald: 「我會爲了做用域作任何事情,可是我不會使用 that = this」(好吧,我還常常用,還爲此感到絲絲驕傲的!我倒!) 我對這個問題更清晰的認識是在我看到Sindre Sorhus更清楚的描述以後: Sindre Sorhus:「在jQuery中使用$this,可是對於純JS我不會,我會使用.bind()」(哭瞎了。。。$this是神馬呀,我只會$(this)啊。。。)
一般,咱們緩存上下文(其實就是對象啦),是這樣的..
var myObj = { specialFunction: function () { }, anotherSpecialFunction: function () { }, getAsyncData: function (cb) { cb(); }, render: function () { var that = this; this.getAsyncData(function () { that.specialFunction(); //注:這裏若是改爲this,會報錯: that.anotherSpecialFunction(); }); } }; myObj.render();Uncaught TypeError:Object[object global] has no methodspecialFunction,由於這裏的this指代的是window(這個參數函數沒有屬於的對象(官方說未綁定對象),so默認爲window的對象(忽略strict模式啦))
然而使用 Function.prototype.bind() 能夠有更加簡潔乾淨的方式:
render: function () { this.getAsyncData(function () { this.specialFunction(); this.anotherSpecialFunction(); }.bind(this)); }
.bind()建立了一個函數,當這個函數在被調用的時候,它的 this 關鍵詞會被設置成被傳入的值(這裏指調用bind()時傳入的參數)。
所以,咱們傳入想要的上下文,this(其實就是 myObj),到.bind()函數中。而後,當回調函數被執行的時候, this 便指向 myObj 對象。
Function.prototype.bind = function (scope) { var fn = this; return function () { return fn.apply(scope); }; }
var foo = { x: 3 } var bar = function(){ console.log(this.x); } bar(); // undefined var boundFunc = bar.bind(foo); boundFunc(); //3
咱們建立了一個新的函數,當它被執行的時候,它的 this 會被設置成 foo —— 而不是像咱們調用 bar() 時的全局做用域。
每一段js代碼(全局代碼或函數)都有一個與之關聯的做用域鏈(scope chain)。
當js須要查找變量x值的時候(這個過程稱爲變量解析(variable resolution)),它會從鏈的第一個對象開始查找,若是這個對象有一個名爲x的屬性,則會直接使用這個屬性的值,若是第一個對象中沒有名爲x的屬性,js會繼續查找鏈上的下一個對象。若是第二個對象依然沒有名爲x的屬性,則會繼續查找下一個,以此類推。
若是做用域鏈上沒有任何一個對象含有屬性x,那麼就認爲這段代碼的做用域鏈上不存在x,並最終拋出一個引用錯誤(ReferenceError)異常。
Array.prototype.unique1 = function () { var n = []; //一個新的臨時數組 for (var i = 0; i < this.length; i++) //遍歷當前數組 { //若是當前數組的第i已經保存進了臨時數組,那麼跳過, //不然把當前項push到臨時數組裏面 if (n.indexOf(this[i]) == -1) n.push(this[i]); } return n; } Array.prototype.unique2 = function() { var n = {},r=[]; //n爲hash表,r爲臨時數組 for(var i = 0; i < this.length; i++) //遍歷當前數組 { if (!n[this[i]]) //若是hash表中沒有當前項 { n[this[i]] = true; //存入hash表 r.push(this[i]); //把當前數組的當前項push到臨時數組裏面 } } return r; } Array.prototype.unique3 = function() { var n = [this[0]]; //結果數組 for(var i = 1; i < this.length; i++) //從第二項開始遍歷 { //若是當前數組的第i項在當前數組中第一次出現的位置不是i, //那麼表示第i項是重複的,忽略掉。不然存入結果數組 if (this.indexOf(this[i]) == i) n.push(this[i]); } return n; }
36. js的事件綁定
本身封裝函數 function myAddEvent( obj, ev ,fn ) //注:此處傳入的ev是不帶"on"的事件名稱 { if ( obj.attachEvent ) { obj.attachEvent( "on" + ev ,fn ); //此處是在IE下 } else { obj.addEventListener ( ev , fn ,false) ; //第三個參數是 是否捕獲 } } //補充的是 IE方式下:{ 綁定事件處理函數: attachEvent( 事件名稱,函數) 解除綁定 : detachEvent( 事件名稱,函數 ) } DOM方式下: { 綁定事件處理函數: addEventListener ( 事件名稱,函數,捕獲 ) 解除綁定 : removeEventListener ( 事件名稱,函數,捕獲) }