今天又是近一天的編碼,雖充實也感受類了,原本是個輕鬆的雙休,結果還要去練車,睡前摘錄一些園子裏看到比較好的內容吧:javascript
(1) 賣技術框架,很是困難,即便有開發者想用,但也不可能掏錢買;css
(2) 技術離市場還很遠,不要太自戀;html
(3) 想掙別人的錢,得先給別人實惠,幫別人掙錢,別總是盤算「若是**,咱們就發達了!」;java
(4) 就連作外包這種感受最簡單的事情,也沒有那麼簡單,有好事,不容易那麼攤你身上的,甲方一到這樣的辦公室,一看到你的穿着打扮,就知道該怎麼辦了,可是咱們這些搞技術的還傻乎乎作着夢。關於這點,我補充一些體會,外包是對等的,好比12306這樣的網站是不可能交給當時我這樣的只有4個全職的公司作的,除非我跟領導人是親戚。任何合做都須要必定基礎,任何人都追求既要保險,又要省錢/掙錢。若是兩者不可兼得,更多人選擇得是保險。咱們那樣的「面子」怎能給予別人安全感?node
(5) 不屑於別人的建議,事實上,有幾個有經驗的投資人讓我放棄作技術平臺,他們給個人一句話是,「國內不少作平臺的公司,最後都作外包了」,我不屑於這種觀點,認爲是「這些公司不像咱們這麼優秀,咱們是特別的」;css3
(6) 市場上須要的不是完美的技術,而是能幫助別人掙錢的技術,若是你自恃本身的技術很完美,那麼,每每會悲劇了,當你看着那些用不怎麼有技術含量的「破東西」掙得一塌糊塗的時候,別提得多失落了;正則表達式
不過,就算咱們犯了那麼多愚蠢的錯誤以後,咱們居然還獲得了幾回天上掉下來的機會,我認爲,咱們當時作對了兩點:(1)咱們很老實;(2)努力作一個好的產品,這個產品自認爲很完美。chrome
「不冒險纔是最大的冒險」,作本身能作的,想本身能想的,管那麼多呢,以爲好就去作,隨心而至,任何人都沒法指引你!編程
在一個函數中會用到全局對象存儲爲局部變量來減小全局查找,由於訪問局部變量的速度要比訪問全局變量的速度更快些數組
function search() { //當我要使用當前頁面地址和主機域名 alert(window.location.href + window.location.host); } //最好的方式是以下這樣 先用一個簡單變量保存起來 function search() { var location = window.location; alert(location.href + location.host); }
若是針對的是不斷運行的代碼,不該該使用setTimeout,而應該是用setInterval,由於setTimeout每一次都會初始化一個定時器,而setInterval只會在開始的時候初始化一個定時器
var timeoutTimes = 0; function timeout() { timeoutTimes++; if (timeoutTimes < 10) { setTimeout(timeout, 10); } } timeout(); //能夠替換爲: var intervalTimes = 0; function interval() { intervalTimes++; if (intervalTimes >= 10) { clearInterval(interv); } } var interv = setInterval(interval, 10);
若是要鏈接多個字符串,應該少使用+=,如
s+=a;
s+=b;
s+=c;
應該寫成s+=a + b + c;
而若是是收集字符串,好比屢次對同一個字符串進行+=操做的話,最好使用一個緩存,使用JavaScript數組來收集,最後使用join方法鏈接起來
var buf = []; for (var i = 0; i < 100; i++) { buf.push(i.toString()); } var all = buf.join("");
和函數相似 ,with語句會建立本身的做用域,所以會增長其中執行的代碼的做用域鏈的長度,因爲額外的做用域鏈的查找,在with語句中執行的代碼確定會比外面執行的代碼要慢,在能不使用with語句的時候儘可能不要使用with語句。
with (a.b.c.d) { property1 = 1; property2 = 2; } //能夠替換爲: var obj = a.b.c.d; obj.property1 = 1; obj.property2 = 2;
般最好用"" + 1來將數字轉換成字符串,雖然看起來比較醜一點,但事實上這個效率是最高的,性能上來講:
("" +) > String() > .toString() > new String()
不少人喜歡使用parseInt(),其實parseInt()是用於將字符串轉換成數字,而不是浮點數和整型之間的轉換,咱們應該使用Math.floor()或者Math.round()
var myVar = "3.14159", str = "" + myVar, // to string i_int = ~ ~myVar, // to integer f_float = 1 * myVar, // to float b_bool = !!myVar, /* to boolean - any string with length and any number except 0 are true */ array = [myVar]; // to array
若是定義了toString()方法來進行類型轉換的話,推薦顯式調用toString(),由於內部的操做在嘗試全部可能性以後,會嘗試對象的toString()方法嘗試可否轉化爲String,因此直接調用這個方法效率會更高
在JavaScript中全部變量均可以使用單個var語句來聲明,這樣就是組合在一塊兒的語句,以減小整個腳本的執行時間,就如上面代碼同樣,上面代碼格式也挺規範,讓人一看就明瞭。
如var name=values[i]; i++;前面兩條語句能夠寫成var name=values[i++]
var aTest = new Array(); //替換爲 var aTest = []; var aTest = new Object; //替換爲 var aTest = {}; var reg = new RegExp(); //替換爲 var reg = /../; //若是要建立具備一些特性的通常對象,也可使用字面量,以下: var oFruit = new O; oFruit.color = "red"; oFruit.name = "apple"; //前面的代碼可用對象字面量來改寫成這樣: var oFruit = { color: "red", name: "apple" };
一旦須要更新DOM,請考慮使用文檔碎片來構建DOM結構,而後再將其添加到現存的文檔中。
for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; document.body.appendChild(el); } //能夠替換爲: var frag = document.createDocumentFragment(); for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; frag.appendChild(el); } document.body.appendChild(frag);
對於大的DOM更改,使用innerHTML要比使用標準的DOM方法建立一樣的DOM結構快得多。
var frag = document.createDocumentFragment(); for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; frag.appendChild(el); } document.body.appendChild(frag); //能夠替換爲: var html = []; for (var i = 0; i < 1000; i++) { html.push('<p>' + i + '</p>'); } document.body.innerHTML = html.join('');
不少人喜歡在JavaScript中使用document.write來給頁面生成內容。事實上這樣的效率較低,若是須要直接插入HTML,能夠找一個容器元素,好比指定一個div或者span,並設置他們的innerHTML來將本身的HTML代碼插入到頁面中。一般咱們可能會使用字符串直接寫HTML來建立節點,其實這樣作,1沒法保證代碼的有效性2字符串操做效率低,因此應該是用document.createElement()方法,而若是文檔中存在現成的樣板節點,應該是用cloneNode()方法,由於使用createElement()方法以後,你須要設置屢次元素的屬性,使用cloneNode()則能夠減小屬性的設置次數——一樣若是須要建立不少元素,應該先準備一個樣板節點
var frag = document.createDocumentFragment(); for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; frag.appendChild(el); } document.body.appendChild(frag); //替換爲: var frag = document.createDocumentFragment(); var pEl = document.getElementsByTagName('p')[0]; for (var i = 0; i < 1000; i++) { var el = pEl.cloneNode(false); el.innerHTML = i; frag.appendChild(el); } document.body.appendChild(frag);
var nodes = element.childNodes; for (var i = 0, l = nodes.length; i < l; i++) { var node = nodes[i]; //…… } //能夠替換爲: var node = element.firstChild; while (node) { //…… node = node.nextSibling;
刪除dom節點以前,必定要刪除註冊在該節點上的事件,無論是用observe方式仍是用attachEvent方式註冊的事件,不然將會產生沒法回收的內存。另外,在removeChild和innerHTML=’’兩者之間,儘可能選擇後者. 由於在sIEve(內存泄露監測工具)中監測的結果是用removeChild沒法有效地釋放dom節點
任何能夠冒泡的事件都不只僅能夠在事件目標上進行處理,目標的任何祖先節點上也能處理,使用這個知識就能夠將事件處理程序附加到更高的地方負責多個目標的事件處理,一樣,對於內容動態增長而且子節點都須要相同的事件處理函數的狀況,能夠把事件註冊提到父節點上,這樣就不須要爲每一個子節點註冊事件監聽了。另外,現有的js庫都採用observe方式來建立事件監聽,其實現上隔離了dom對象和事件處理函數之間的循環引用,因此應該儘可能採用這種方式來建立事件監聽
//避免屢次取值的調用開銷 var h1 = element1.clientHeight + num1; var h2 = element1.clientHeight + num2; //能夠替換爲: var eleHeight = element1.clientHeight; var h1 = eleHeight + num1; var h2 = eleHeight + num2;
最小化訪問NodeList的次數能夠極大的改進腳本的性能
var images = document.getElementsByTagName('img'); for (var i = 0, len = images.length; i < len; i++) { }
編寫JavaScript的時候必定要知道什麼時候返回NodeList對象,這樣能夠最小化對它們的訪問
要了解了當使用NodeList對象時,合理使用會極大的提高代碼執行速度
可使用下面幾種方式來優化循環
大多數循環使用一個從0開始、增長到某個特定值的迭代器,在不少狀況下,從最大值開始,在循環中不斷減值的迭代器更加高效
因爲每次循環過程都會計算終止條件,因此必須保證它儘量快,也就是說避免屬性查找或者其它的操做,最好是將循環控制量保存到局部變量中,也就是說對數組或列表對象的遍歷時,提早將length保存到局部變量中,避免在循環的每一步重複取值。
var list = document.getElementsByTagName('p'); for (var i = 0; i < list.length; i++) { //…… } //替換爲: var list = document.getElementsByTagName('p'); for (var i = 0, l = list.length; i < l; i++) { //…… }
循環體是執行最多的,因此要確保其被最大限度的優化
在JavaScript中,咱們可使用for(;;),while(),for(in)三種循環,事實上,這三種循環中for(in)的效率極差,由於他須要查詢散列鍵,只要能夠,就應該儘可能少用。for(;;)和while循環,while循環的效率要優於for(;;),多是由於for(;;)結構的問題,須要常常跳轉回去。
var arr = [1, 2, 3, 4, 5, 6, 7]; var sum = 0; for (var i = 0, l = arr.length; i < l; i++) { sum += arr[i]; } //能夠考慮替換爲: var arr = [1, 2, 3, 4, 5, 6, 7]; var sum = 0, l = arr.length; while (l--) { sum += arr[l]; }
最經常使用的for循環和while循環都是前測試循環,而如do-while這種後測試循環,能夠避免最初終止條件的計算,所以運行更快。
當循環次數是肯定的,消除循環並使用屢次函數調用每每會更快。
若是要提升代碼性能,儘量避免出現須要按照JavaScript解釋的字符串,也就是
使用eval至關於在運行時再次調用解釋引擎對內容進行運行,須要消耗大量時間,並且使用Eval帶來的安全性問題也是不容忽視的。
不要給setTimeout或者setInterval傳遞字符串參數
var num = 0; setTimeout('num++', 10); //能夠替換爲: var num = 0; function addNum() { num++; } setTimeout(addNum, 10);
if (oTest != '#ff0000') { //do something } if (oTest != null) { //do something } if (oTest != false) { //do something } //雖然這些都正確,但用邏輯非操做符來操做也有一樣的效果: if (!oTest) { //do something }
if (a > b) { num = a; } else { num = b; } //能夠替換爲: num = a > b ? a : b;
因爲JavaScript是弱類型的,因此它不會作任何的自動類型檢查,因此若是看到與null進行比較的代碼,嘗試使用如下技術替換
全局變量應該所有字母大寫,各單詞之間用_下劃線來鏈接。儘量避免全局變量和函數, 儘可能減小全局變量的使用,由於在一個頁面中包含的全部JavaScript都在同一個域中運行。因此若是你的代碼中聲明瞭全局變量或者全局函數的話,後面的代碼中載入的腳本文件中的同名變量和函數會覆蓋掉(overwrite)你的。
//糟糕的全局變量和全局函數 var current = null; function init(){ //... } function change() { //... } function verify() { //... } //解決辦法有不少,Christian Heilmann建議的方法是: //若是變量和函數不須要在「外面」引用,那麼就可使用一個沒有名字的方法將他們全都包起來。 (function(){ var current = null; function init() { //... } function change() { //... } function verify() { //... } })(); //若是變量和函數須要在「外面」引用,須要把你的變量和函數放在一個「命名空間」中 //咱們這裏用一個function作命名空間而不是一個var,由於在前者中聲明function更簡單,並且能保護隱私數據 myNameSpace = function() { var current = null; function init() { //... } function change() { //... } function verify() { //... } //全部須要在命名空間外調用的函數和屬性都要寫在return裏面 return { init: init, //甚至你能夠爲函數和屬性命名一個別名 set: change }; };
由於JavaScript能夠在任什麼時候候修改任意對象,這樣就能夠以不可預計的方式覆寫默認的行爲,因此若是你不負責維護某個對象,它的對象或者它的方法,那麼你就不要對它進行修改,具體一點就是說:
若是循環引用中包含DOM對象或者ActiveX對象,那麼就會發生內存泄露。內存泄露的後果是在瀏覽器關閉前,即便是刷新頁面,這部份內存不會被瀏覽器釋放。
簡單的循環引用:
var el = document.getElementById('MyElement'); var func = function () { //… } el.func = func; func.element = el;
可是一般不會出現這種狀況。一般循環引用發生在爲dom元素添加閉包做爲expendo的時候。
function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } } init();
init在執行的時候,當前上下文咱們叫作context。這個時候,context引用了el,el引用了function,function引用了context。這時候造成了一個循環引用。
下面2種方法能夠解決循環引用:
1) 置空dom對象
function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } } init(); //能夠替換爲: function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } el = null; } init();
將el置空,context中不包含對dom對象的引用,從而打斷循環應用。
若是咱們須要將dom對象返回,能夠用以下方法:
function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } return el; } init(); //能夠替換爲: function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } try { return el; } finally { el = null; } } init();
2) 構造新的context
function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } } init(); //能夠替換爲: function elClickHandler() { //…… } function init() { var el = document.getElementById('MyElement'); el.onclick = elClickHandler; } init();
把function抽到新的context中,這樣,function的context就不包含對el的引用,從而打斷循環引用。
IE下,腳本建立的dom對象,若是沒有append到頁面中,刷新頁面,這部份內存是不會回收的!
function create() { var gc = document.getElementById('GC'); for (var i = 0; i < 5000; i++) { var el = document.createElement('div'); el.innerHTML = "test"; //下面這句能夠註釋掉,看看瀏覽器在任務管理器中,點擊按鈕而後刷新後的內存變化 gc.appendChild(el); } }
將dom元素的innerHTML設置爲空字符串,能夠釋放其子元素佔用的內存。
在rich應用中,用戶也許會在一個頁面上停留很長時間,可使用該方法釋放積累得愈來愈多的dom元素使用的內存。
在rich應用中,隨着實例化對象數量的增長,內存消耗會愈來愈大。因此應當及時釋放對對象的引用,讓GC可以回收這些內存控件。
對象:obj = null
對象屬性:delete obj.myproperty
數組item:使用數組的splice方法釋放數組中不用的item
對string的方法調用,好比'xxx'.length,瀏覽器會進行一個隱式的裝箱操做,將字符串先轉換成一個String對象。推薦對聲明有可能使用String實例方法的字符串時,採用以下寫法:
var myString = new String('Hello World');
http://www.cnblogs.com/elegance/p/4288435.html
console.log( !!window===true );
var a=1,b=2; a=[b,b=a][0];//執行完這句代碼以後 a的值爲2 b的值爲1了
var day=(new Date).getDay()===0; //傳統if語句 if (day) { alert('Today is Sunday!'); }; //運用邏輯與代替if day&&alert('Today is Sunday!');//也就是說只有day爲真的狀況才執行後面的代碼alert 一句簡單的代碼就實現了上面的if功能 強大吧
if (!a) { a = {}; } //上面的三句話能夠用下面的一句話替換哦 a = a || {}; //解釋這句話一下哦 若是有a這個變量的聲明的話 那麼它仍是原來的對象 若是沒有就給它建立一個對象
與其這樣書寫:if(string.length > 0){..}
不如這樣書寫:if(string.length){..}
你們都知道在任何編程語言中,若是被除數爲0則會報錯,而在js裏面不會,它返回的值爲NAN,NaN表示一個不能產生正常結果的運算結果,咱們能夠用isNaN(number)來檢測是否是NAN,可是你們也許都不知道NAN不等於任何值,包括它自身。
將script標籤設置爲type='text'而後能夠在裏面保存任意信息,以後能夠在JavaScript代碼中很方便地獲取。
頁面代碼以下所示:
<script type="text" id="angelaScript"> <h1>這個標題1是不會顯示出來的,能夠用這種方式保存信息哦!</h1> </script> <script type="text/javascript"> console.log(document.getElementById('angelaScript').innerHTML); </script>
結果顯示以下圖所示:
看上圖運行的效果,總結一句哦!
看下面的switch的使用,你瞬間以爲switch這麼厲害!
html頁面代碼以下所示
<div id="angelaDiv"> </div> <script type="text/javascript"> console.log(angelaDiv); </script>
在chrome控制檯看到的結果以下圖所示
你們都知道字符串是不可變的,在js中也是如此。也就是說一旦字符串被建立,就沒法改變。可是我相信不多人知道在js當中竟然能夠用下標來訪問字符串當中的某一個字符,雖然能夠用下標讀取但去不能修改哦(雖然修改操做不會報錯,可是卻不起做用)
var s = 'str1 , str2 , str3';s.split(/\s(,)\s/,4); //輸出結果:["str1",",","str2",","]
瀏覽器地址欄輸入如下代碼,立馬就把瀏覽器變成notepad了,厲害吧!
data:text/html, <html contenteditable>
你們都知道css裏面用text-align:center加上margin:0 auto就能夠實現水平居中了,可是垂直居中卻沒有相應的css屬性來設置,而若是要設置元素可以垂直居中必須得將容器設置爲display:table,而後將子元素也就是要垂直居中顯示的元素設置爲display:table-cell,而後加上vertical-align:middle來實現。
看代碼吧!下面的代碼利用css3的transform來實現垂直居中和水平居中
.center-vertical { position: relative; top: 50%; transform: translateY(-50%); } .center-horizontal { position: relative; left: 50%; transform: translateX(-50%); }