前端不為人知的一面--前端冷知識集錦
原文:https://www.cnblogs.com/Wayou/p/things_you_dont_know_about_frontend.html
前端已經被玩兒壞了!像console.log()可以向控制檯輸出圖片等炫酷的玩意已經不是什麼新聞了,像用||操作符給變數賦預設值也是人盡皆知的舊聞了,今天看到Quora上一個帖子,瞬間又GET了好多前端技能,一些屬於技巧,一些則是聞所未聞的冷知識,一時間還消化不過來。現分類整理出來分享給大家,也補充了一些平時的積累和擴充套件了一些內容。
HTML篇
瀏覽器位址列執行JavaScript程式碼
這個很多人應該還是知道的,在瀏覽器位址列可以直接執行JavaScript程式碼,做法是以javascript:開頭後跟要執行的語句。比如:
javascript:alert('hello from address bar :)');
將以上程式碼貼到瀏覽器位址列回車後alert正常執行,一個彈窗神現。
需要注意的是如果是通過copy paste程式碼到瀏覽器位址列的話,IE及Chrome會自動去掉程式碼開頭的javascript:,所以需要手動新增起來才能正確執行,而Firefox中雖然不會自動去掉,但它根本就不支援在位址列執行JS程式碼,sigh~
這一技術在我的另一篇博文《讓Chrome 接管郵件連線,收發郵件更方便了》中有使用到,利用在瀏覽器位址列中執行JavaScript程式碼將Gmail設定為系統的郵件接管程式。
瀏覽器位址列執行HTML程式碼
如果說上面那條小祕密知道的人還算多的話,這條祕笈知道的人就要少一些了,在非IE核心的瀏覽器位址列可以直接執行HTML程式碼!
比如在位址列輸入以下程式碼然後回車執行,會出現指定的頁面內容。
data:text/html,<h1>Hello, world!</h1>
你造麼,可以把瀏覽器當編輯器
還是瀏覽器位址列上做文章,將以下程式碼貼到位址列執行後瀏覽器變成了一個原始而簡單的編輯器,與Windows自帶的notepad一樣,吼吼。
data:text/html, <html contenteditable>
歸根結底多虧了HTML5中新加的contenteditable屬性,當元素指定了該屬性後,元素的內容成為可編輯狀態。
推而廣之,將以下程式碼放到console執行後,整個頁面將變得可編輯,隨意踐踏吧~
document.body.contentEditable='true';
利用a標籤自動解析URL
很多時候我們有從一個URL中提取域名,查詢關鍵字,變數引數值等的需要,而萬萬沒想到可以讓瀏覽器方便地幫我們完成這一任務而不用我們寫正則去抓取。方法就在JS程式碼裡先建立一個a標籤然後將需要解析的URL賦值給a的href屬性,然後就得到了一切我們想要的了。
var a = document.createElement('a'); a.href = 'http://www.cnblogs.com/wayou/p/'; console.log(a.host);
利用這一原理,稍微擴充套件一下,就得到了一個更加健壯的解析URL各部分的通用方法了。下面程式碼來自James的部落格。
function parseURL(url) { var a = document.createElement('a'); a.href = url; return { source: url, protocol: a.protocol.replace(':',''), host: a.hostname, port: a.port, query: a.search, params: (function(){ var ret = {}, seg = a.search.replace(/^\?/,'').split('&'), len = seg.length, i = 0, s; for (;i<len;i++) { if (!seg[i]) { continue; } s = seg[i].split('='); ret[s[0]] = s[1]; } return ret; })(), file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1], hash: a.hash.replace('#',''), path: a.pathname.replace(/^([^\/])/,'/$1'), relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1], segments: a.pathname.replace(/^\//,'').split('/') }; }
頁面擁有ID的元素會建立全域性變數
在一張HTML頁面中,所有設定了ID屬性的元素會在JavaScript的執行環境中建立對應的全域性變數,這意味著document.getElementById像人的闌尾一樣顯得多餘了。但實際專案中最好老老實實該怎麼寫就怎麼寫,畢竟常規程式碼出亂子的機會要小得多。
<div id="sample"></div> <script type="text/javascript"> console.log(sample); </script>
載入CDN檔案時,可以省掉HTTP標識
現在很流行的CDN即從專門的伺服器載入一些通用的JS和CSS檔案,出於安全考慮有的CDN伺服器使用HTTPS方式連線,而有的是傳統的HTTP,其實我們在使用時可以忽略掉這個,將它從URL中省去。
<script src="//domain.com/path/to/script.js"></script>
這一點在之前一篇譯文部落格《jQuery程式設計最佳實踐》中也有提到。
利用script標籤儲存任意資訊
將script標籤設定為type='text'然後可以在裡面儲存任意資訊,之後可以在JavaScript程式碼中很方便地獲取。
<script type="text" id="template"> <h1>This won't display</h1> </script>
var text = document.getElementById('template').innerHTML
CSS篇
關於CSS的惡作劇
相信你看完以下程式碼後能夠預料到會出現什麼效果。
*{ cursor: none!important; }
簡單的文字模糊效果
以下兩行簡單的CSS3程式碼可達到將文字模糊化處理的目的,出來的效果有點像使用PS的濾鏡,so cool!
p { color: transparent; text-shadow: #111 0 0 5px; }
垂直居中
有好多次博主都有這樣的需求,垂直居中顯示某個DIV,我們知道CSS中天然有水平居中的樣式text-align:center。唯獨這個垂直居中無解。
當然你可以將容器設定為display:table,然後將子元素也就是要垂直居中顯示的元素設定為display:table-cell,然後加上vertical-align:middle來實現,但此種實現往往會因為display:table而破壞整體佈局,那還不如直接用table標籤了呢。
下面這個樣式利用了translate來巧妙實現了垂直居中樣式,需IE9+。
.center-vertical { position: relative; top: 50%; transform: translateY(-50%); }
相比而言,水平居中要簡單得多,像上面提到的text-align:center,經常用到的技巧還有margin:0 auto。但對於margin大法也只在子元素寬度小於容器寬度時管用,當子元素寬度大於容器寬度時此法失效。
如法炮製,利用left和transform同樣可實現水平居中,不過意義不大,畢竟text-align和margin差不多滿足需求了。
.center-horizontal { position: relative; left: 50%; transform: translateX(-50%); }
多重邊框
利用重複指定box-shadow來達到多個邊框的效果
/*CSS Border with Box-Shadow Example*/ div { box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.2), 0 0 0 12px rgba(0, 0, 0, 0.2), 0 0 0 18px rgba(0, 0, 0, 0.2), 0 0 0 24px rgba(0, 0, 0, 0.2); height: 200px; margin: 50px auto; width: 400px }
實時編輯CSS
通過設定style標籤的display:block樣式可以讓頁面的style標籤顯示出來,並且加上contentEditable屬性後可以讓樣式成為可編輯狀態,更改後的樣式效果也是實時更新呈現的。此技巧在IE下無效。擁有此技能者,逆天也!
<!DOCTYPE html> <html> <body> <style style="display:block" contentEditable> body { color: blue } </style> </body> </html>
建立長寬比固定的元素
通過設定父級視窗的padding-bottom可以達到讓容器保持一定的長度比的目的,這在響應式頁面設計中比較有用,能夠保持元素不變形。
<div style="width: 100%; position: relative; padding-bottom: 20%;"> <div style="position: absolute; left: 0; top: 0; right: 0; bottom: 0;background-color:yellow;"> this content will have a constant aspect ratio that varies based on the width. </div> </div>
CSS中也可以做簡單運算
通過CSS中的calc方法可以進行一些簡單的運算,從而達到動態指定元素樣式的目的。
.container{ background-position: calc(100% - 50px) calc(100% - 20px); }
JavaScript篇
生成隨機字串
利用Math.random和toString生成隨機字串,來自前一陣子看到的一篇博文。這裡的技巧是利用了toString方法可以接收一個基數作為引數的原理,這個基數從2到36封頂。如果不指定,預設基數是10進位制。略屌!
function generateRandomAlphaNum(len) { var rdmString = ""; for (; rdmString.length < len; rdmString += Math.random().toString(36).substr(2)); return rdmString.substr(0, len); }
整數的操作
JavaScript中是沒有整型概念的,但利用好位操作符可以輕鬆處理,同時獲得效率上的提升。
|0和~~是很好的一個例子,使用這兩者可以將浮點轉成整型且效率方面要比同類的parseInt,Math.round 要快。在處理畫素及動畫位移等效果的時候會很有用。效能比較見此。
var foo = (12.4 / 4.13) | 0;//結果為3 var bar = ~~(12.4 / 4.13);//結果為3
順便說句,!!將一個值方便快速轉化為布林值 !!window===true 。
重寫原生瀏覽器方法以實現新功能
下載的程式碼通過重寫瀏覽器的alert讓它可以記錄彈窗的次數。
(function() { var oldAlert = window.alert, count = 0; window.alert = function(a) { count++; oldAlert(a + "\n You've called alert " + count + " times now. Stop, it's evil!"); }; })(); alert("Hello World");
關於console的惡作劇
關於重寫原生方法,這裡有個惡作劇大家可以拿去尋開心。Chrome的console.log是支援對文字新增樣式的,甚至log圖片都可以。於是可以重寫掉預設的log方法,把將要log的文字應用到CSS的模糊效果,這樣當有人試圖呼叫console.log()的時候,出來的是模糊不清的文字。好冷,我表示沒有笑。
是從這篇G+帖子的評論裡看到的。使用之後的效果是再次呼叫log會輸出字跡模糊不清的文字。
var _log = console.log; console.log = function() { _log.call(console, '%c' + [].slice.call(arguments).join(' '), 'color:transparent;text-shadow:0 0 2px rgba(0,0,0,.5);'); };
不宣告第三個變數的值交換
我們都知道交換兩個變數值的常規做法,那就是宣告一箇中間變數來暫存。但鮮有人去挑戰不宣告中間變數的情況,下面的程式碼給出了這種實現。蠻有創意 的。
var a=1,b=2;a=[b,b=a][0];
萬物皆物件
在JavaScript的世界,萬物皆物件。除了null和undefined,其他基本型別數字,字串和布林值都有對應有包裝物件。物件的一個特徵是你可以在它身上直接呼叫方法。對於數字基本型別,當試圖在其身上呼叫toString方法會失敗,但用括號括起來後再呼叫就不會失敗了,內部實現是用相應的包裝物件將基本型別轉為物件。所以(1).toString()相當於new Number(1).toString()。因此,你的確可以把基本型別數字,字串,布林等當物件使用的,只是注意語法要得體。
同時我們注意到,JavaScript中數字是不分浮點和整形的,所有數字其實均是浮點型別,只是把小數點省略了而以,比如你看到的1可以寫成1.,這也就是為什麼當你試圖1.toString()時會報錯,所以正確的寫法應該是這樣:1..toString(),或者如上面所述加上括號,這裡括號的作用是糾正JS解析器,不要把1後面的點當成小數點。內部實現如上面所述,是將1.用包裝物件轉成物件再呼叫方法。
If語句的變形
當你需要寫一個if語句的時候,不妨嘗試另一種更簡便的方法,用JavaScript中的邏輯操作符來代替。
var day=(new Date).getDay()===0; //傳統if語句 if (day) { alert('Today is Sunday!'); }; //運用邏輯與代替if day&&alert('Today is Sunday!');
比如上面的程式碼,首先得到今天的日期,如果是星期天,則彈窗,否則什麼也不做。我們知道邏輯操作存在短路的情況,對於邏輯與表示式,只有兩者都真才結果才為真,如果前面的day變數被判斷為假了,那麼對於整個與表示式來說結果就是假,所以就不會繼續去執行後面的alert了,如果前面day為真,則還要繼續執行後面的程式碼來確定整個表示式的真假。利用這點達到了if的效果。
對於傳統的if語句,如果執行體程式碼超過了1 條語句,則需要加花括號,而利用逗號表示式,可以執行任意條程式碼而不用加花括號。
if(conditoin) alert(1),alert(2),console.log(3);
上面if語句中,如果條件成立則執行三個操作,但我們不需要用花括號將這三句程式碼括起來。當然,這是不推薦的,這裡是冷知識課堂:)
禁止別人以iframe載入你的頁面
下面的程式碼已經不言自明瞭,沒什麼好多說的。
if (window.location != window.parent.location) window.parent.location = window.location;
console.table
Chrome專屬,IE繞道的console方法。可以將JavaScript關聯陣列以表格形式輸出到瀏覽器console,效果很驚讚,介面很美觀。
//採購情況 var data = [{'品名': '杜雷斯', '數量': 4}, {'品名': '岡本', '數量': 3}]; console.table(data);