javascript雜記一


title: javascript雜記一
date: 2017-05-21 14:34:25
tags: javascript筆記


this的基本用法

首先有一個函數

function fn1(){
    alert(this);
}

直接調用則this指向window

fn1();  // 指向window;

如果是被元素對象調用

div.onclick = function(){
    var _this = this;    // 這個this指的就是div元素對象
    fn1();    // 這裏打印的this值的就是window,因爲上面fn1函數的環境就是在全局,所以如果直接調用函數,那麼this都是window
}

div.onclick = fn1;    // 這裏打印的this就是div元素對象,這裏已經改變了fn1函數的環境,賦值給了div元素對象的事件屬性中,環境自然也從全局變爲div元素對象。

判斷瀏覽器名稱

function myBrowser(){
    var userAgent = navigator.userAgent;   //取得瀏覽器的userAgent字符串
    if (userAgent.indexOf("Opera") > -1) {   //判斷是否Opera瀏覽器
        return "Opera"
    };
    if (userAgent.indexOf("Firefox") > -1) { //判斷是否Firefox瀏覽器
        return "FF";
    };
    if (userAgent.indexOf("Chrome") > -1){  //判斷是否Chrome瀏覽器
        return "Chrome";
    }
    if (userAgent.indexOf("Safari") > -1) { //判斷是否Safari瀏覽器
        return "Safari";
    }
    if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1) {  //判斷是否IE瀏覽器
        return "IE";
    };
}

火狐瀏覽器禁止頁面滾動

if (navigator.userAgent.toLowerCase().indexOf('firefox')>=0){
    if (e.preventDefault)
    e.preventDefault();
    e.returnValue = false;
}

鼠標滾輪事件

非FireFox瀏覽器是使用onmousewheel事件,而FireFox瀏覽器使用DOMMouseScroll事件。

非FireFox瀏覽器使用的是wheelDelta方法判斷滾動方向,FireFox瀏覽器使用的是detail方法判斷滾動方向。

wheelDelta:-120和detail:3 代表向下滾動。wheelDelta:120和detail:-3代表向上滾動。

document.body.onmousewheel = function(event) {
    event = event || window.event;
    console.log(event.wheelDelta)
};

document.body.addEventListener("DOMMouseScroll", function(event) {
    console.log(event.detail)
});

jquery兼容性的滾輪事件

$('#scrollSelect-view').on("mousewheel DOMMouseScroll", function (e) {

    var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? 1 : -1)) ||        // chrome & ie
                (e.originalEvent.detail && (e.originalEvent.detail > 0 ? -1 : 1));                  // firefox

    if (delta > 0) {
        // 向上滾
        console.log("wheelup");
    } else if (delta < 0) {
        // 向下滾
        console.log("wheeldown");
    }
});

自定義屬性

有時候寫方法時會定義大量變量,有的變量其實比較多餘,很多數據可以存儲到元素對象的自定義屬性中去。這樣不用去考慮作用域的問題,因爲只要這個元素對象存在在這個方法內就可以去使用,但是最好只保存和這個元素對象有關的屬性。

比如:下面代碼就是,在事件處理函數內部只能獲取i循環完畢之後的值,而通過把i的值作爲元素對象的自定義屬性賦值,就沒有作用域的限制。

for(var i = 0; i < 5; i++) {
    div.index = i;
    div[i].onclick = function(){
        alert(i);
        alert(this.index);
    }
}

排他思想和清空上一個

排他

通常在tab欄切換中經常用到排他,比如有10個選項,只有當前項纔有背景色,通常顏色是通過一個類名掛鉤到css中去設置的,那麼排他就是每次先將所有導航選項的類名清空,然後只給當前點擊的這個元素對象添加類名。

for(var i = 0;i < Lis.length;i++){
    Lis[i].index = i;
    Lis[i].onclick = function(){
        // 這裏開始排他
        for(var i = 0; i < Lis.length;i++){
            Lis[i].className = '';
        }
        // 單獨設置當前選項
        Lis[this.index].className = 'active';
    };
};

清空上一個

這種效果除了排他之外還可以通過清除上一個選項來完成。創建一個變量存儲上一個選中元素,在點擊當前元素時候清空上一個類名,之後把自己賦值給這個變量,如此每次只需要清空一個元素的類名即可。

var oElem = null;
// 初始化,默認第一個元素是當前項
Lis[0].className = 'active';
Elem = Lis[0];

for(var i = 0;i < Lis.length;i++){
    Lis[i].index = i;
    Lis[i].onclick = function(){
        // 這裏開始清空上一個
        Elem.className = '';
        Elem = this;
        Lis[this.index].className = 'active';
    };
};

jquery的stop()方法

$(selector).stop(stopAll,goToEnd)

stopAll 可選。規定是否停止被選元素的所有加入隊列的動畫。

goToEnd 可選。規定是否允許完成當前的動畫。該參數只能在設置了 stopAll 參數時使用。

使用懶加載插件

使用的 jquery.lazyload

調用下載好的插件

$(function(){
    $("img.imglazyload").lazyload({
        threshold : 200,
        effect : "fadeIn"
    });
});

html部分,一定要在外層包一個div並且設置寬高,不要用圖片去撐開。

<div class="item-image">
    <img class="imglazyload" data-original="圖片地址">
</div>

js中的NaN

  1. NaN是一個數字類型但不是一個數值。
  2. 出現NaN肯定是進行了非法操作而不是獲取數值有錯,如果獲取數值有錯是undefind。
  3. NaN與自己本身也是不相等的。
  4. NaN轉爲布爾是false。
  5. NaN本身的意思是'不是一個數值'

isNaN可以判斷某些類型是不是一個數字類型。如果判斷到是一個數字爲false(不是一個數值這個判定是錯的),而不是數字類型的是true(不是一個數值這個判定是對的)。

NaN在判斷時是在內部使用Number()方法轉換,所以是不是數字類型的依據主要是看Number()轉出的是什麼類型。比如布爾值、空字符串、字符串數字都會被認爲是數字類型而返回false。

js的作用域基礎

作用域實際上是瀏覽器js解析器的一種工作方式。

瀏覽器的js解析器在讀取javascript代碼時會先提升變量和函數,再去逐行解讀代碼。這是每個作用域的解析步驟。

預解析

根據var、function、參數 找一些東西。

首先js解析器會搜索所有var和function找到所有變量,var聲明的變量提升時值都是未定義,提升function時候會將整個函數代碼塊一起提升。

當var和function重名時,會保留function,覆蓋var,但是如果兩個以上同名的function,那麼就看聲明的先後順序了。

逐行解析

變量提升之後,js解析器會開始逐行解析代碼,這時只有表達式可以改變變量的值,用下邊的案例來說明。

alert(a);   // function a(){alert(4);}
var a = 1;
alert(a);   // 1
function a(){alert(2);}
alert(a);   // 1
var a = 3;
alert(a)    // 3
function a(){alert(4);}
alert(a);   // 3

a();    // 報錯

第一個alert打印出函數的原因是變量提升的規則,後面的a打印的都是變量的值而不是函數,因爲變量賦值是一種表達式,而函數只是一個聲明並不是表達式。並且因爲現在a是一個數值,所以調用時自然會報錯。

多組script

自上而下的作用域大部分指的是多組script標籤,如下代碼

<script>
    alert(a);   // 報錯
</script>
<script>
    var a = 1;
</script>
<script>
    alert(a);   // 1
</script>
/

如果碰到這種情況,js解析器會對每個script代碼塊進行獨立預解析和逐行解析,第一塊script的代碼還沒聲明a,第二塊script的代碼聲明和賦值了,這時到第三塊script代碼塊時a已經聲明並賦值了,所以直接會打印1。

函數

由內而外主要指函數,一個函數也是一個單獨的作用域,javascript中,函數是唯一能分隔作用域的。

var a = 1;
function fn1(){
    alert(a);
    var a = 2;
}
fn1();      // undefined
alert(a);   // 1
var a = 1;
function fn1(){
    alert(a);
    a = 2;
}
fn1();      // 1
alert(a);   // 2

第一個例子中在函數內部聲明瞭a,那麼在fn1中的a變量就和上級作用域的a變量沒有任何關係了。按照預解析的步驟這裏打印的是undefined。

第二個例子沒有聲明a變量,所以在fn1作用域中就找不到a,這時就會去上級作用域中尋找,上級作用域聲明瞭a並且賦值爲1了,所以打印1。

如果是下面這種情況

var a = 1;
function fn1(a){
    alert(a);
    a = 2;
}
fn1();      // undefined
alert(a);   // 1
var a = 1;
function fn1(a){
    alert(a);
    a = 2;
}
fn1(a);     // 1
alert(a);   // 2

參數其實就是一個局部變量,第一個例子沒有傳參,參數就相當於var a; 第二個例子傳了參數就相當於var a = 1;

一個函數的解析順序是先從參數開始的。

下面看一個最常見的案例

for(var i = 0; i < 3; i++){
    btn[i].onclick = function(){
        alert(i);   // 3
    }
}

最開始我以爲這裏打印的i是會隨着遍歷打印出0,1,2的,但實際上onclick函數中相當於一個獨立的作用域,這個作用域中沒有聲明i變量,所以就要去上級作用域去獲取,那爲什麼是3呢,因爲函數只有在點擊時纔會調用,只有調用時纔會發生預解析和逐步解析,這時去獲取i的值上級作用域早已遍歷完畢。

js運算符%取餘的應用

下面的例子中要在li元素中添加背景色,顏色存儲在arr數組。如果不用取餘運算符只能寫兩層for循環,而使用取餘運算,可以直接讓取餘後的值自己循環。

arr的長度是3,i是0開始每次+1,那麼arr數組每次的索引就是:arr[0%3=0],arr[1%3=1],arr[2%3=2],arr[3%3=0],arr[4%3=1],arr[5%3=2],arr[6%3=0],這樣就達到了遍歷顏色數組的目的。這種操作很適合於在一個數組的遍歷內部又需要遍歷另外一個數組的情況。

var li = document.getElementsByTagName('li');
var arr = ['yellow','pink','orange'];
for(var i = 0; i < li.length; i++){
    li[i].style.backgroundColor = arr[i%arr.length];
}

下面擴展一下這個案例,加上任意li元素點擊後變色,再去點擊另一個li,另一個li元素變色,上一個li元素變回原來的顏色。通常這種功能會用排他來做,這次不用排他,使用取餘操作來寫。

var li = document.getElementsByTagName('li');
var arr = ['yellow','pink','orange'];
var elem = null;

for(var i = 0; i < li.length; i++){
    li[i].index = i;
    li[i].style.backgroundColor = arr[i%arr.length];

    li[i].onclick = function(){
        if(elem){
            elem.style.backgroundColor = arr[elem.index%arr.length];
        }
        elem = this;
        this.style.backgroundColor = 'gray';
    }
}

排他是將所有li元素變色,再去更改當前點擊的元素的背景色,而這種思路是記錄上一次點擊的元素,在下一次點擊時只改變上一次點擊的元素的背景色就可以了。這裏elem.index和i的作用是相同的。

另外取餘操作還可以換算時間,比如現在要將70秒轉爲分鐘,那麼可以這樣寫

var s = 70;
var m = Math.floor( 70/60 + '分' + 70%60 + '秒');

js獲取瀏覽器計算後的屬性值

像width或者height這種屬性直接獲取只能得到行內樣式,如果不寫在行內就獲取不到,使用getComputerStyle可以獲取瀏覽器計算後的樣式,也就是被瀏覽器渲染之後得到的元素實際的屬性的值。格式是getComputerStyle(element).width;

但是這個方法在ie6、7、8不兼容。這三個非標準瀏覽器使用的currentStyle屬性。格式是element.currentStyle.width;

不要用這兩個方法去獲取沒有設置過的屬性。

不能用這兩個屬性去獲取複合樣式,比如要獲取背景色不要用background而是要用backgroundColor,不論css是怎麼寫的,都要寫具體的屬性。因爲如果寫background的話會獲取到所有這個屬性可以設置的屬性值,如果css沒寫的會獲取到默認的。

另外在firefox瀏覽器4.0版本之前,getComputerStyle的參數要寫兩個,第二個參數可以隨便寫比如getComputerStyle(element,'').width;getComputerStyle(element,true).width;,總之只要寫一個參數就可以。

jq中的即使搜索事件

在jq中實現input搜索框的即時搜索和其他即時性的改變需要用到input和propertychange(兼容ie8及以下瀏覽器)事件。

input是標準的瀏覽器事件,一般應用於input元素,當input的value發生變化就會發生,無論是鍵盤輸入還是鼠標黏貼的改變都能及時監聽到變化。

propertychange只要當前對象屬性發生改變都會觸發,所以使用propertychange時最好排除一下不想觸發事件的元素。

window.parent

在b.html頁面使用iframe的時候,引入一個Html頁面名稱暫定爲a.html,呢麼在a.html中,window指的是a的window對象,而window.parent指的就是b.html的window對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章