JavaScript 「跑馬燈」抽獎活動代碼解析與優化(一)

最近的項目中作了一個「跑馬燈」的抽獎特效插件。上篇文章已經分享過htmlcss 的相關知識。這篇文章主要分享一些 JavaScript 相關的知識。這幾天在寫這篇文章的時候,也順便把本身的代碼重構了一下。
這裏主要是來寫寫本身的優化過程。俗話說:javascript

一個程序猿的進步是從對本身的代碼不滿意開始的。css

開始以前先來看上篇文章遺漏的兩個問題和幾個知識點,是本身重構的過程當中須要用到的:html

1.移動端1px像素線的問題

對於設計師給個人手機端網頁的設計稿都是2倍圖。按照道理來講,在寫網頁的時候,全部對象的實際尺寸都是會除2。可是對於1像素的線呢?
先來看兩張圖,設計稿的效果:java

這裏寫圖片描述
在三星 S4下的實際顯示效果:node

這裏寫圖片描述
能夠看到這個時候1px的線居然顯示不出來了。這個問題是跟 S4手機的屏幕像素密度有關。關於屏幕像素密度和1px 線的關係有不少文章介紹,能夠自行搜索瞭解。我這裏的解決方案是,對1px 的線不作處理。是多少就寫多少。就算個人基礎單位是rem,也不是其它單位。jquery

{
    position: absolute;
    width: 13rem;
    height: 9.2rem;
    border:1px solid #000;
}

2.pc 端瀏覽器和移動端瀏覽器容錯率的差別

先來看一段代碼:git

$('[node-type=row-a').find('div');

很明顯能夠發現,我使用的選擇器是有語法錯誤的。可是在瀏覽器中運行會有什麼結果呢?看下圖:
這裏寫圖片描述github

很明顯能夠看出對於屬性選擇器,就算我有語法錯誤,PC 端瀏覽器也是能夠正確解析的。可是在手機端,這種寫法是不可以正確解析,代碼不可以運行。web

因此寫代碼的時候必定要注意一些小細節哈。。。數組

3.jQuery中選擇器的使用

在使用 jQuery 或者是 Zepto 的過程當中最常用的選擇器的寫法就是下面這樣吧,

$('div.testClass')

只是在$() 中寫上本身須要的 Dom 節點的 class或者 ID 或 者使用屬性選擇器。
在查看 jQuery的文檔,對於$()會有這樣的描述:

jQuery([selector,[context]])

最重要的是看看對 context (它也是咱們平時使用中最容易忽略,可是卻很是有用的一個參數)的描述:

默認狀況下, 若是沒有指定context參數,$()將在當前的 HTML document中查找 DOM 元素;若是指定了 context 參數,如一個 DOM 元素集或 jQuery 對象,那就會在這個 context 中查找。在jQuery 1.3.2之後,其返回的元素順序等同於在context中出現的前後順序。

剛開始學習 JavaScript 那會兒,就據說了操做 DOM 是很損耗瀏覽器性能,遍歷 DOM 也是很影響程序性能的。
若是咱們在指定的範圍內查找須要的 Dom 會不會比從整個document 中查找快不少。並且在咱們寫 web 組件的過程當中,一個頁面上組件可能出現不少次,那咱們怎麼判斷咱們要操做哪一個組件呢?這個context參數就會起到決定行的做用。具體請繼續看哇。。。

4.jQuery對象到數組的轉換

剛開始學習 jQuery的時候在一本書上看到一句話:

jQuery對象就是一個 JavaScript 數組。

並且在使用 jQuery的過程當中,都會遇到,js對象轉 jQuery對象,jQuery對象轉 js對象。關於這些基礎不作過多介紹。
可是有時候咱們會想在 jQuery對象上運用一些原生Array對象的方法或者屬性。來看一個簡單的例子:
這裏寫圖片描述

由圖中的代碼運行結果,能夠知道在 jQuery對象上是沒有咱們要使用reverse方法的。儘管test是一個數組
那麼咱們怎麼辦纔可讓 jQuery對象使用原生的 Array對象的方法呢?

4.1使用原型鏈擴展

好比下面的代碼:

jQuery.prototype.reverse=function(){
    //一些操做
}

使用prototype來擴展方法的時候,你們一直比較認爲是缺點的就是可能會污染已經存在的原型鏈上的方法。還有就是訪問方法的時候須要查找原型鏈。

4.2將 jQuery對象中的對象添加到數組中

看下面的代碼

var test = $('div.test');
var a=[];
$(test).each(function(){
    a.push($(this));
});

a.reverse();

這樣就能夠將 jQuery對象翻轉。

4.3使用 Array對象的 from()方法

這種方法也是本身在編寫插件過程當中使用的方法。看一下文檔描述:

Array.from() 方法能夠將一個類數組對象或可迭代對象轉換成真實的數組。

我的感受使用這個代碼比較簡潔。暫時還不知道有沒有性能的影響。繼續看下面的代碼:

var test = $('div.test');
var a= Array.from(test);
a.reverse();

5.setInterval()和setTimeout()對程序性能的影響

由於setTimeout()setInterval()這兩個函數在 JavaScript 中的實現機制徹底同樣,這裏只拿 setTimeout()驗證

那麼來看兩段代碼

var a ={
    test:function(){
        setTimeout(this.bbb,1000);
    },
    bbb:function(){
        console.log('----');
    }
};
a.test()

輸出結果以下:
這裏寫圖片描述

看下面的代碼輸出是什麼

var a ={
    test:function(){
        setTimeout(function(){
            console.log(this);
            this.bbb();
        },1000);
    },
    bbb:function(){
        console.log('----');
    }
};
a.test();

運行這段代碼的時候,代碼報錯
這裏寫圖片描述

由以上的結果能夠知道,當咱們在使用setInterval()setTimeout()的時候,在回掉中使用this的時候,this的做用域已經發生了改變,而且指向了 window

setTimeout(fn,0)的含義是,指定某個任務在主線程最先可得的空閒時間執行,也就是說,儘量早得執行。它在"任務隊列"的尾部添加一個事件,所以要等到同步任務和"任務隊列"現有的事件都處理完,纔會獲得執行。

意思就是說在咱們設置 setTimeout()以後,也可能不是當即等待多少秒以後就當即執行回掉,而是會等待主線程的任務都處理完後再執行,因此存在 "等待"超過本身設置時間的現象。同時也會存在異步隊列中已經存在了其它的 setTimeout() 也是會等待以前的都執行完再執行當前的。

看一個 Demo:

setTimeout(function bbb(){},4000);

function aaa(){
    setTimeout(function ccc(){},1000);
}

aaa();

若是運行上面的代碼,當執行完 aaa() ,JavaScript 線程空閒,這時開始計時:等待1秒後將 ccc()加入執行隊列,等待4s 將 bbb() 加入執行隊列。這時從 ccc()加入執行隊列到 bbb()加入執行隊列中間時間間隔是3s。

執行結果以下圖:

這裏寫圖片描述

這裏寫圖片描述

相關文章
相關標籤/搜索