- createDocumentFragment的使用
首先,介紹了幾種常見的動態建立html節點的方法,以下所示:
方法 |
說明 |
crateAttribute(name) |
用指定名稱name建立特性節點 |
createComment(text) |
建立帶文本text的註釋節點 |
createDocumentFragment() |
建立文檔碎片節點 |
createElement(tagname) |
建立標籤名爲tagname的節點 |
createTextNode(text) |
建立包含文本text的文本節點 |
以上這些方法,每次JavaScript對DOM的操做都會改變當前頁面的呈現,並從新刷新整個頁面,從而消耗了大量的時間。爲解決這個問題,能夠建立一個文檔碎片,把全部的新節點附加其上,而後把文檔碎片的內容一次性添加到document中,這個就是createDocumentFragment()的用武之處。
createDocumentFragment()說明
DocumentFragment:表示文檔的一部分(或一段),更確切地說,它表示一個或多個鄰接的 Document 節點和它們的全部子孫節點。
DocumentFragment 節點不屬於文檔樹,繼承的 parentNode 屬性老是 null。
不過它有一種特殊的行爲,該行爲使得它很是有用,即當請求把一個DocumentFragment 節點插入文檔樹時,插入的不是 DocumentFragment 自身,而是它的全部子孫節點。這使得 DocumentFragment 成了有用的佔位符,暫時存放那些一次插入文檔的節點。它還有利於實現文檔的剪切、複製和粘貼操做。
能夠用Document.createDocumentFragment() 方法建立新的空 DocumentFragment 節點。
說明:添加多個dom元素時,先將元素append到DocumentFragment中,最後統一將DocumentFragment添加到頁面。 該作法能夠減小頁面渲染dom元素的次數。經IE和FireFox下測試,在append1000個元素時,效率能提升10%-30%,FireFox下提高較爲明顯。
createDocumentFragment()用法示例
使用appendChild逐個向DOM文檔中添加1000個新節點:
for (var i = 0; i < 1000; i++)
{
var el = document.createElement('p');
el.innerHTML = i;
document.body.appendChild(el);
}
使用createDocumentFragment()一次性向DOM文檔中添加1000個新節點:
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);
不要小瞧這10%-30%,效率的提升是着眼於多個細節的,若是咱們能在不少地方都能讓程序運行速度提升10%-30%,那將是一個質的飛躍,您也將步入骨灰級玩家的行列。
1、將條件分支,按可能性順序從高到低排列
說明:能夠減小解釋器對條件的探測次數。 javascript
2、在同一條件子的多(>2)條件分支時,使用switch優於if
說明:switch分支選擇的效率高於if,在IE下尤其明顯。4分支的測試,IE下switch的執行時間約爲if的一半。 html
3、使用三目運算符替代條件分支
使用前:
if (a > b)
{ num = a; }
else
{ num = b; }
使用後:
num = a > b ? a : b; java
-
JS循環引用的內存泄露問題
若是循環引用中包含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種方法能夠解決循環引用
- 置空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();
- 構造新的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的引用,從而打斷循環引用。
-
Javascript中聲明變量速度的研究
聲明變量到底要不要var
- 使用var語句屢次聲明一個變量不只是合法的,並且也不會形成任何錯誤。
- 若是重複使用的一個聲明有一個初始值,那麼它擔當的不過是一個賦值語句的角色。
- 若是重複使用的一個聲明沒有一個初始值,那麼它不會對原來存在的變量有任何的影響。
沒有var聲明的變量,是做爲全局變量存在的;有var聲明的變量,屬於局部變量,尤爲是在函數內部。而且,通過測試,帶var聲明比不帶var速度要快,好比:"var a"比"a"具備更快的執行速度。咱們有理由推測,局部變量的聲明比全局變量的聲明效率更高。 直接量與new
變量有好幾種類型,可是同一類型的變量建立的方式可能不同,好比string、Object、Array等這些類型的變量聲明或者建立。
通過測試,經過直接量聲明的速度明顯快於經過new聲明的速度,好比"var a={} "比"var a=new Object()"具備更快的執行速度。 局部變量與全局變量
如今筆者來告訴你,函數內儘可能多設局部變量,這樣即安全又快速,變量操做也更加合理,不會由於函數內胡亂操做全局變量而致使邏輯錯誤。
寫個例子說明下,先創建一個全局變量:var m=1; ,接着我讀取這個全局變量1000000次
全局變量:
for(var i=1000000;i--;)
{a=m;}
局部變量:
(function (){
var n=m;
for(var i=1000000;i--;)
{a=n;}
})();
執行速度2>1
經過上面測試代表,先將m這個全局變量的值存給局部變量n,在將n賦值給a具備更快的速度。
變量名長度
變量名是本身取的,爲了照顧語義和規範,變量名可能稍長,可是注意了,變量名的長度也會影響代碼的執行速度。
通過測試,長的變量名聲明的執行速度沒有短的快,好比"var a=1"比"var aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1"具備更快的執行速度。
因此,咱們在聲明變量的時候,儘可能縮寫一些單詞,並記憶一些常見的縮寫,如下是縮寫示例:
單詞 |
縮寫 |
array(數組) |
arr |
string(字符串) |
str |
number(數量/數字) |
num |
function(函數) |
fun |
message(消息/信息) |
mes |
userNumber(會員數量) |
userNum/uNum |
parentElement(父級節點/父級元素) |
parentEle |
returnArray(返回的數組) |
returnArr |
-
JS全局變量的反作用
JavaScript經過函數管理做用域。局部變量是在函數內部使用 var 聲明的變量;全局變量則會在下列狀況下出現:
- 在任何地方不使用 var 聲明變量,或者直接向未聲明的變量賦值。
- 在函數外部使用 var 聲明的變量。
- 以 window. variable 形式聲明的變量。
全局變量的問題在於,你的JavaScript應用程序和web頁面上的全部代碼都共享了這些全局變量,他們住在同一個全局命名空間,因此當程序的兩個不一樣部分定義同名但不一樣做用的全局變量的時候,命名衝突在所不免。
web頁面包含不是該頁面開發者所寫的代碼也是比較常見的,例如:
- 第三方的JavaScript庫
- 廣告方的腳本代碼
- 第三方用戶跟蹤和分析腳本代碼
- 不一樣類型的小組件,標誌和按鈕
比方說,該第三方腳本定義了一個全局變量,叫作result;接着,在你的函數中也定義一個名爲result的全局變量。其結果就是後面的變量覆蓋前面的,第三方腳本就一會兒嗝屁啦!
所以,要想和其餘腳本成爲好鄰居的話,應該儘量少的使用全局變量,而且始終使用var來聲明變量。
如下是幾種常見的誤將局部變量聲明爲全局變量的例子。
1、函數內部不使用 var 聲明變量
function sum(x, y) {
// 不推薦寫法: 隱式全局變量
result = x + y;
return result;
}
此段代碼中的result沒有聲明。代碼照樣運做正常,但在調用函數後你最後的結果就多一個全局命名空間,這能夠是一個問題的根源。
經驗法則是始終使用var聲明變量,正如改進版的sum()函數所演示的:
function sum(x, y) {
var result = x + y;
return result;
}
2、使用任務鏈進行部分 var 聲明
// 反例,勿使用
function foo() {
var a = b = 0;
// ...
}
上面的片斷中,a是本地變量可是b確實全局變量,這可能不是你但願發生的。
此現象發生的緣由在於這個從右到左的賦值,首先,是賦值表達式b = 0,此狀況下b是未聲明的。這個表達式的返回值是0,而後這個0就分配給了經過var定義的這個局部變量a。換句話說,就比如你輸入了:
var a = (b = 0);
若是你已經準備好聲明變量,使用鏈分配是比較好的作法,不會產生任何意料以外的全局變量,如:
function foo() {
var a, b;
// ... a = b = 0; // 兩個均局部變量
}
IT學苑提示隱式全局變量和明肯定義的全局變量間有些小的差別,就是經過delete操做符讓變量未定義的能力:
- 經過var建立的全局變量(任何函數以外的程序中建立)是不能被刪除的。
- 無var建立的隱式全局變量(無視是否在函數中建立)是能被刪除的。
這代表,在技術上,隱式全局變量並非真正的全局變量,但它們是全局對象的屬性。屬性是能夠經過delete操做符刪除的,而變量是不能的。
使用即時函數函數,避免變量污染
爲了不全局的變量的污染,IT學苑推薦一種即時函數的寫法,即將具備獨立功能的代碼放在一個即時函數裏面。以下:
(function(){
//輸出變量 itxueyuan
var itxueyuan="http://www.itxueyuan.com/javascript/";
document.write(itxueyuan+"<br />");
})();
document.write(itxueyuan);
結果,第一次輸出http://www.itxueyuan.com/javascript/,第二次提示語法錯誤:
![](http://static.javashuo.com/static/loading.gif)
可見,變量itxueyuan的做用域僅限於及即時函數內部,有效避免了變量的污染,尤爲是在引入第三方代碼的狀況下。因爲IT學苑的JS代碼很大一部分使用了這種模式,有效避免了變量衝突。