妙味課堂——JavaScript基礎課程筆記


集中時間把秒微課堂JS的基礎課程看完,並且認真完成了課后練習。感覺在JS方面的技能算是入了個門了。課后練習的作業完成的代碼我都匯總在了這里。至於視頻課的學習筆記,則記錄如下。

第01課JS入門基礎_熱身課程

寫JS的步驟

  1. 先實現布局
  2. 想出實現原理
  3. 了解JS語法

希望把某個元素移除的實現

  • display: none; 顯示為無
  • visibility: hidden; 隱藏
  • width \ height
  • 透明度
  • left \ top
  • 拿與背景色相同的div蓋住該元素
  • 利用margin值
  • ……

獲取元素

  • getElementById() ——靜態方法,前面只能跟document
  • document.body、document.title 頁面中只有一個的元素
  • getElementsByTagName() ——動態方法,前面可以跟document也可以跟其他元素,返回的是一個類似數組的元素的集合
    • 有類似數組的length
    • 有類似數組的應用方式,比如ali[0]
    • 在用TagName的時候,必須要加上中括號[]
    • 所謂的動態方法,是指通過js動態添加的元素,getElementsByTagName()也可以找到,但是document.getElementById是找不到的

事件

事件:鼠標事件、鍵盤事件、系統事件、表單事件、自定義事件

  • onclick
  • onmouseover
  • onmousedown
  • onmouseout
  • onmouseup
  • onmousemove
  • ……

如何添加事件

  • 元素.onmouseover

函數

函數可以理解為命令,做一些事情,如:

function abc() { //肯定不會主動執行! … }

  1. 直接調用:abc();
  2. 事件調用:元素.事件 = 函數名 (oDiv.onclick = abc;)
  3. ……

function(){} 匿名函數

元素.事件 = function(){}

測試

  • alert(1); 帶確定按鈕的警告框;alert(‘ok’); ‘ok’ 字符串
  • 初學者:最好保持隨時寫,隨時測試的習慣

變量

var li = document.getElementById(‘lis’);
var num = 123;
var name = ‘leo’;

第02課HTML屬性操作

  • 屬性名
  • 屬性值

  • 屬性的讀操作:獲取、找到
    • 元素.屬性名
  • 屬性的寫操作:替換、修改
    • 元素.屬性名 = 新的值
    • 添加的話,需要用 +=
  • innerHTML 讀取元素內的所有HTML代碼

字符串連接:加號

屬性讀寫操作的注意事項

  • JS屬性中不允許出現“-”,例如font-size改為fontSize
  • class在js里面是保留字,在js作用class要用className
  • 所有的相對路徑都別拿來做判斷(如img的src、還有href)
  • 顏色值不要拿來做判斷(因為有red、#f00、rgb(250, 0, 0)等寫法
  • 相對路徑也不要拿來做判斷
  • innerHTML的值別拿來做判斷
  • IE6、IE7、IE8中表單元素的type更改不了,不支持,會報錯;其他的都可以。
  • 在有些瀏覽器中,直接更改float值可能不支持。在js中,可以用IE(styleFloat)和非IE(cssFloat)來區別對待。
  • 不能用來做判斷的東西,可以創造一個開關,利用布爾值來實現

關於兼容:

  • 技術上:必須能做到掌握兼容性(兼容性問題的解決方案)
  • 需求上:商量着來(提供最准確的呈現方案)

[]中括號的使用

  • 點“.”后面的值無法修改
  • 中括號[]里面的值可以修改;JS中允許把”.”替換成“[]”

條件判斷

  • if(條件){……};
  • if(條件){……} else {……};
  • if(條件1){……} else if(條件2) {……} else if(條件3) {……} else {……};

數組

  • “放數據的倉庫”
  • 中括號[],半角都好分隔,最后一個數據后面不要加逗號
  • 數組的length屬性
  • 為數組最后塞東西用push();

for應用

for循環的使用場景:

  • 如果想要重復執行某些代碼
  • 每次執行的時候,有個數字在變化

for循環的執行順序:1→234→234……

  1. var i = 0;
  2. i < 3; 關鍵步驟
  3. 括號里面的所有代碼
  4. i++

注意下面這樣一個循環

for (var i=0; i<aLi.length; i++) {
  aLi[i].onclick = function(){
    alert(i);
  }
}

cssText文本格式化與屬性操作

  • oDiv.style.cssText = ‘width: 200px; height: 200px;’;
  • cssText不會動head的style中的設置;但是會改變行間樣式(注意,是替換行間樣式,而非新增行間樣式)

按鈕點擊之后,不再重復功能的思路

  1. 找按鈕的麻煩,比如點擊一次之后,設置oBtn.disabled = true;
  2. 繼續找按鈕的麻煩,比如點擊一次后,將按鈕隱藏oBtn.style.display = ‘none’;
  3. 將按鈕添加的東西清空,然后再添加一次,先清空再生成
  4. 用判斷

this指向及this應用

window是js中的”老大“

function fn1(){
    alert(this);
}
fn1();

上述代碼中執行函數fn1()相當於window.fn1();因此,在函數體內彈出這個this仍然是window。

function fn1(){
    alert(this);
}
oBtn.onclick = fn1;

上述用按鈕的點擊事件調用的fn1函數,最終彈出來的是這個按鈕,而不是window。

function fn1(){
    alert(this);
}
oBtn.onclick = function(){
    alert(this)
}

上述代碼,點擊按鈕彈出的this仍然是oBtn這個按鈕。

function fn1(){
    alert(this);
}
oBtn.onclick = function(){
    fn1();
}

上述代碼,點擊oBtn按鈕,彈出的就不再是oBtn這個對象,而是window。

<input id="btn2" type="button" value="按鈕2" onclick="alert(this)" />

述代碼中,彈出的this就是window。

  • this: 調用當前方法(函數)的那個對象
    function fn1(){
        this
    }
    
    fn1(); this => window
    
    oDiv.onclick = fn1; this => oDiv
    
    oDiv.onclick = function(){
        this => oDiv
    };
    
    oDiv.onclick = function(){
        fn1(); fn1()里面的this => window
    }
    
    <div onclick="  this  "></div> this => div
    
    <div onclick = "  fn1();  "></div>  fn1()里面的this => window
    <script>
    
    fn1(this);
    function fn1(obj){
      obj => window
    }
    
    oDiv.onclick = function(){
      this
      fn1(this);
    };
    function fn1(obj){ obj => oDiv }
    
    </script>
    <input type="button" value="按鈕1" />
    <input type="button" value="按鈕2" />
    <input type="button" value="按鈕3" />
    
    window.onload = function(){
      var aBtn = document.getElementsByTagName('input');
      for(var i=0; i<aBtn.length; i++) {
        aBtn[i].onclick = function(){
          this.style.background = 'yellow';
        }
      }
    }

    上述代碼還等價於下面這段代碼:

  • <input type="button" value="按鈕1" />
    <input type="button" value="按鈕2" />
    <input type="button" value="按鈕3" />
    
    window.onload = function(){
      var aBtn = document.getElementsByTagName('input');
      
      for(var i=0; i<a.aBtn.length; i++) {
        aBtn[i].onclick = fn1; //注意不要在fn1后面加括號
      }
      
      function fn1(){
        this.style.background = 'yellow';
      }
    }

     

第03課:自定義屬性、索引值

 自定義屬性的讀寫操作

winddow.onload = function(){
  var aBtn = document.getElementsByTagName('input');
  
  aBtn[0].abc = 123; //自定義屬性
  
  // alert(aBtn[0].abc); 自定義屬性的讀
  // aBtn[0].abc = 456; 自定義屬性的寫
}

JS可以為任何HTML元素添加任意個自定義屬性

自定義屬性應用

用自定義屬性可以元素添加開關屬性,作為控制開關。如下面這個例子:

window.onload = function(){
  var aLi = document.getElementsByTagName('li');
  // var onOff = true; 一個onOff只能控制一個開關。要為多個元素設置各自的開關,就要給每個元素加個onOff開關。
  
  for(var i=0; i<aLi.length; i++) {
    aLi[i].onOff = true;
    aLi[i].onclick = function(){
      if (this.onOff){
        this.style.background = 'url(img/active.png)';
        this.onOff = false;
      } else {
        this.style.background = 'url(img/normal.png)';
        this.onOff = true;
      }
    }
  }

獲取自身遞增數字及匹配數組內容

在網頁上設置三個按鈕,默認值為0,每點擊一次按鈕,字母依次ABCD輪換。

<input type="button" value="0" />
<input type="button" value="0" />
<input type="button" value="0" />

var aBtn = document.getElementsByTagName('input');
  var arr = ['A', 'B', 'C', 'D'];
  
  for(var i=0; i<aBtn.length; i++){
    aBtn[i].num = 0;
    aBtn[i].onclick = function(){
      this.value = arr[this.num]
      this.num++;
      if(this.num === arr.length){
        this.num = 0;
      };
    };
  };

添加索引值、匹配數組、HTML元素

把三個按鈕的value與數組里面的值依次進行匹配。

<input type="button" value="btn1" />
<input type="button" value="btn2" />
<input type="button" value="btn3" />

window.onload = function(){
  var aBtn = document.getElementsByTagName('input');
  var arr = ['莫濤','張森','杜鵬'];
  
  for(var i=0; i<aBtn.length; i++){
    aBtn[i].index = i; //自定義屬性index,添加索引值
    aBtn[i].onclick = function(){
      //alert(i); //不會彈出1、2,直接彈出3,也就是aBtn的長度。也就是說,在基礎階段,在for循環所包的函數里面再用i是不靠譜的。
      this.value = arr[this.index];
    };
  };

上面是通過索引值匹配數組值,匹配HTML中的元素也是同理。

想建立”匹配“、”對應“關系,就用索引值。

第04課:JS數據類型、類型轉換

數據類型

  • HTML標簽類型:
    • block
    • inline
    • inline-block
    • table
    • ……
  • JS中的數據類型:
    • 數字(NaN屬於數字類型)
    • 字符串
    • 布爾值
    • 函數類型
    • 對象
      • obj
      • []
      • {}
      • null (空是不能添加自定義屬性的)
    • 未定義 undefined

typeof用來判斷數據類型。

字符串方法charAt():通過字符串的下標獲取子字符串。

對象可以添加自定義屬性。如果把函數扔給了對象,就給該對象添加了一個方法。

JS數據類型轉換

把字符串轉成數字的方法:

JS方法:Number();

var a = '100';
alert(a + 100); //'100100'

var b = '00100';
alert(Number(b)); //100

var c = '+100';
alert(Number(c)); //100

var d = '';
alert(Number(d)); //0

var e = '   ';
alert(Number(e)); //0

var f = true;
alert(Number(f)); //1

var g = false;
alert(Number(g)); //0

var i = [];
alert(Number(i)); //0 空數組用Number轉出來是0

var j = [''];
alert(Number(j)); //0

var k = [123];
alert(Number(k)); //123

var l = ['123'];
alert(Number(l)); //123

var o = null;
alert(Number(o)); //0

----------------------------
var m = [1,2,3];
alert(Number(m)); //NaN

var json = {abc:123};
alert(Number(json)); //NaN

var json2 = {};
alert(Number(json2)); //NaN 即使是空json,Number方法也轉不了

var h = function(){};
alert(Number(h)); //NaN

var p;
alert(Number(p)); //undefined 

var q = '100px';
alert(Number(q)); // NaN

parseInt與parseFloat

var a = '100px';
alert(parseInt(a)); //100

var b = '100px123456789';
alert(parseInt(b)); //100

var d = '-100px';
alert(parseInt(d)); //-100 parseInt還是認加減號的

var e = '   100px';
alert(parseInt(e)); //100 parseInt也是認空格的

var f = '000000100px';
alert(parseInt(f)); //100

var g = '12.34元';
alert(parseInt(g)); //12 parseInt只能轉出整數
------------------------------
var c = true;
alert(parseInt(c)); //NaN

//parseInt也不能用於轉函數等

parseInt()方法還有一個參數,就是按照幾進制來轉,比如parseInt(a, 10);表示按照十進制來轉;parseInt(b, 2);表示按照二進制來轉。

var a = '12.34元';
alert(parseFloat(a)); //12.34

var b = '12.3.4元';
alert(parseFloat(b)); //12.3 parseFloat只認第一個小數點

parseInt和parseFloat的配合使用,可以來判斷某個值是整數還是小數,如下:

var num = '200.345';
if(parseInt(num) == parseFloat(num)) {
  alert(num + '是整數');
} else {
  alert(num + '是小數');
}

JS中稀奇古怪的隱式類型轉換

顯式類型轉換(強制類型轉換):

  • Number();
  • parseInt();
  • parseFloat();

隱式類型轉換:

  • - * \/ \% 減、乘、除、取模可以將字符串轉成數字
  • + 加號可以將數字轉成字符串
  • ++ -- 加加、減減運算符可以把字符串轉成數字
  • < > 大於號、小於號可以把字符串轉成數字,一定要注意是進行數字的比較還是字符串的比較
  • ! 取反 把右邊的數據類型轉成布爾值
  • ==
  • alert('200' - 3); //197
    alert(200 + '3'); //2003
    
    var a = '10';
    a++;
    alert(a); //11
    
    alert('10'>9); //true
    alert('1000000'>'9'); //false
    //注意:數字的比較和字符串的比較不同;字符串的比較是一位一位的比較。
    
    alert(!'ok'); //false
    alert(!100); //false
    
    alert('2' == 2); //true
    alert('2' === 2); //false 三個等號不僅判斷值,還會先判斷兩者的類型

    隱式類型轉換轉不出來,也會返回一個NaN,例如:alert(‘……’ - 9);就會彈出NaN。

    isNaN應用實例

    NaN: (not a number)。Nan是個不是數字的數字類型。所有的數字都是數字類型,但不是所有的數字類型都是數字。

    • NaN是個數字類型,但它不是個數字。
    • 一旦寫程序中出現了NaN,肯定說明進行了非法的運算操作。
    • NaN是個false。
    • NaN與自己都不相等。
    var a = Number('abc');
    //alert(a); //NaN
    //alert(typeof(a)); //number
    
    if(a) { //會彈出‘假’,說明NaN是false
      alert('真');
    } else {
      alert('假');
    }
    
    //alert(a === a); //false NaN比較,比出false

    isNaN:is not a Number 是不是不是個數字(不是數字)。

    isNaN();是個方法,用來干活的。

    • 幫助判斷某些值是不是數字。
    • 不喜歡數字、討厭數字(不是討厭數字類型,isNaN遇到NaN就很喜歡,會返回true,但是NaN就是個數字類型) 用來判斷數字。如alert(isNaN(2)); 返回false。alert(isNaN(‘我愛你’)); 返回true。alert(isNaN(function(){})); 返回true。

    isNaN的判斷過程,將括號里面的東西扔給Number,Number轉出來數字,就返回false;轉不出來就返回true。

  • alert(isNaN('250'));
    //Number() '250' => 250 => false
    
    alert(isNaN(true));
    //Number() true => 1 => false
    
    alert(isNaN([]));
    //Number() [] => 0 => false

    下面是一個isNaN的小應用:

  • <input type="text" />
    <input type="button" value="判斷輸入值是不是數字" />
    window.onload = function(){
      var aInp = document.getElementsByTagName('input');
      var str = '';
      
      aInp[1].onclick = function(){
        str = aInp[0].value
        //alert(type of str); //總是返回string 從HTML中拿到的內容,類型都是字符串
        
        if(isNaN(str)){
          alert(str + '不是數字');
        } else {
          alert(str + '是數字');
        }
      }
    }

     

第05課:函數傳參、重用、價格計算

參數 = JS的數據類型:

  • 數字
  • 字符串
  • 布爾值
  • 函數
  • 對象
  • 未定義

參數類型判斷

fn1(100);
fn1('miaov');
fn1(function(){alert(1);});

function fn1(a){
  if(typeof a === 'number' && a === a) {
    alert(a+20);
  } else if (typeof a === 'string'){
    alert(a.charAt(2));
  } else if (typeof a === 'function'){
    a();
  }
}

重用代碼步驟

  1. 盡量保證HTML代碼結構一致,可以通過父級選取子元素
  2. 把核心的主程序實現,用函數包起來
  3. 把每組里不同的值找出來,通過傳參實現

第06課:作用域、JS預解析機制

什么是作用域

  • 域:空間、范圍、區域
  • 作用:讀、寫

瀏覽器的“JS解析器”

“JS解析器”:瀏覽器中專門用來讀JS的程序。它至少做下面兩件事(當然還有其他事情):

  1. 准備工作(“找一些東西”):根據var、function、參數找東西 —— JS的預解析

    a = 未定義 所有的變量,在正式運行代碼之前,都提前賦了一個值:未定義 fn1 = function fn1(){alert(2);} 所有的函數,在正式運行代碼之前,都是整個函數塊

    遇到重名的,只留一個

  2. 逐行解讀代碼 每讀一行,就會回到預解析的庫里面去看一眼。 碰上表達式(帶有 = + - * / % ++ – ! 參數……都是表達式)能夠改變值的是表達式。碰上表達式,就到庫里面去修改值。

  3. alert(a); //未定義
    var a=1; //在庫里面a的值由未定義換成1
    function fn1(){alert(2);}
    alert(a); //彈出:function a(){alert(4);}
    var a=1; //預解析中的a改為了1
    alert(a);  //彈出1
    function a(){alert(2);}//函數聲明,沒有改變a的值。什么也沒發生。
    alert(a); //繼續彈出1,因為a在預處理庫里面的值沒有被改過。
    var a=3; //預處理中a的值變為3
    alert(a); //彈出3
    function a(){alert(4);} //函數聲明,什么也沒有發生
    alert(a); //繼續彈出3
    a(); //報錯 a is not a function

    以上代碼在預解析中的過程如下:

    1)預解析: var function 參數 …… 讀到 var a = 1 => a 未定義 讀到 function a(){alert(2);} => a = functiona(){alert(2);} 變量與函數重名了,就只留下函數: a = function(){alert(2);} 讀到 var a = 3 => a 未定義,這里與上面名為a的函數重名了,所以還是保留a = function(){alert(2);} 讀到function a(){alert(4);} => a = function a(){alert(4);} 與前面的 a = function(){alert(2);}重名,根據上下文,后面的函數覆蓋了前面的函數,所以預解析就只留下了 a = function(){alert(4);} 2)逐行解讀代碼 讀到表達式,表達式可以修改預解析的值。參數也可以改變預解析的值。 遇到函數調用,又要做兩件事:預解析、逐行解析代碼 函數聲明,不是表達式,不改變預解析里面的值。

作用域

  • 在<script>標簽里面聲明的函數和變量,都是全局函數和全局變量(但是js解析器要把一塊的事情處理完,然后處理另外一塊事情)自上而下
  • 函數:函數也是個域,也是先找后執行。由里到外
  • 對象 {}

作用域鏈:從子級作用域跳到父級作用域的過程

第07課:運算符、流程控制

算術

  • + 加
  • - 減
  • * 乘
  • / 除
  • % 取模(求余數)

賦值

  • =
  • +=
  • -=
  • *=
  • /=
  • %=

關系

  • <
  • >
  • <=
  • >=
  • ==
  • !=
  • ===
  • !===

邏輯

  • && 與
  • || 或
  • ! 否

運算優先級

  • 括號

程序流程控制

判斷

  • if
  • switch (case break default)
  • ?:

循環

  • while
  • for

跳出、跳過

  • break
  • continue

什么是真,什么是假

  • 真:非零的數字、字符串、true、函數、object:[] {} 能找到的元素
  • 假:零、NaN、空字符串、false、null、未定義、不能找到的元素

第08課:return、定時器基礎

  • return 返回值:函數名+括號(例如fn1())就相當於得到了該函數里面return后面的值
  • 所有函數默認返回值是:undefined
  • 可返回:數字、字符串、布爾、函數、對象(元素、[]、{}、null)、未定義
  • return后面的任何代碼都不執行了
  • alert fn1();
    function fn1(){
        return function(){
            alert(1);
        }
    }
    此時彈出的是:function(){alert(1);}
    
    alert fn1()();
    function fn1(){
        return function(){
            alert(1);
        }
    }
    此時彈出的是1,也就是return的匿名函數執行的結果。
    
    alert fn1()(10);
    function fn1(){
        return function(a){
            alert(a);
        }
    }
    此時彈出的是10。
    
    alert fn1(20)(10);
    function fn1(a){
        return function(b){
            alert(a + b);
        }
    }
    此時彈出的是30。

    arguments

    fn1(1, 2, 3); //實參——實際傳遞的參數

    function fn1(a, b, c) //形參——形式上,a、b、c這些名代表1、2、3

    如果不寫形參,1、2、3也能夠傳進來,都存在arguments的肚子里。

    function fn1(){ //arguments => [1, 2, 3] —— 實參的集合(不是數組,但是類似數組,有length,也可以用下標找到其中的數據) }

    當函數參數個數無法確定的時候,用arguments:

  • alert(sum(1,2,3));
    function sum(){
        var n=0;
        for(var i=0; i<arguments.length; i++){
            n += arguments[i];
        }
        return n;
    }
    var a=1;
    function fn2(a){ //arguments的某個數值就相當於某個形參
        arguments[0]=3;
        alert(a); //彈出3
        var a=2;
        alert(arguments[0]); //彈出2
    }
    fn2(a);
    alert(a); //彈出1

    currentStyle與getComputedStyle應用

    • getComputedStyle獲取的是計算機(瀏覽器)計算后的樣式,但是不兼容IE6、7、8
    • currentStyle方法兼容IE6、7、8,但是不兼容標准瀏覽器

    屬性判斷法、版本檢測法來解決瀏覽器間的兼容性問題 ~~~ js function getStyle( obj, attr) { return obj.currentStyle ? obj.currentStyle[attr]:getComputedStyle( obj )[attr]; } ~~~

    注意事項:

    • 如果用以上的方法獲取某個元素的復合樣式,例如background,那么就不要用上面那種方式獲取,在不同瀏覽器間有兼容性問題。用上面的方法獲得單一樣式,而不要用來獲取復合樣式。
    • 使用以上方法,注意不要多按空格
    • 使用以上方法,不要獲取未設置后的樣式,因為瀏覽器間不兼容
    • 在火狐4.0之前,有個bug,如果getComputedStyle后面不跟參數,會出現問題,所以有些人寫成getComputedStyle(obj, false),那個false就是為了解決這個bug。這里的bug也可以寫成0,或者其他任何參數都可以。不過目前火狐的瀏覽器都比較高,因此這個問題已經不是很常見了。

第09課:定時器管理、函數封裝

setInterval

setInterval(函數, 毫秒); 重復執行(發動機)

var i=0;
function fn1(){
    document.title = i;
    i++;
}
setInterval(fn1, 1000);

事件調用的方法

  • fn1(); 直接調用
  • document.onclick = fn1; 事件調用
  • setInterval(fn1, 1000); 函數調用

clearInterval

var timer = setInterval(函數, 毫秒); //重復執行
clearInterval(timer); //清除定時器
var i=0,
    timer = null;
function fn1(){
    i++;    
    document.title = i;
    
    if(i===10){
        clearInterval(timer);
    }
}
timer = setInterval(fn1, 1000);

注意

定時器如果是由事件控制的,比如按鈕的onclick控制的,那么一定要遵循一個原則,先關后開。這樣可以避免連續點擊多次按鈕,重復設置定時器。另外,clearInterval()不論里面填的是一個timer,還是null還是未定義,都可以順利運行。

setTimeout

var timer = setTimeout(函數, 毫秒); 執行一次(炸彈)

clearTimeout(timer);

定時器的小應用(函數封裝和回調函數)

doMove的函數封裝

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>無標題文檔</title>
<style>
#div1 { width:100px; height:100px; background:red; position:absolute; top:50px; left:30px; }
</style>
</head>

<body>

<input id="btn1" type="button" value="走" />
<div id="div1"></div>

<script>
var oBtn1 = document.getElementById('btn1');
var oDiv = document.getElementById('div1');

oBtn1.onclick = function () {
    
    // doMove ( oDiv, 'width', 34, 600 );
    doMove ( oDiv, 'left', 12, 900, function () {
        doMove ( oDiv, 'top', 34, 500 );
    });

};

function doMove ( obj, attr, dir, target, endFn ) {
    
    dir = parseInt(getStyle( obj, attr )) < target ? dir : -dir;
    
    clearInterval( obj.timer );
    
    obj.timer = setInterval(function () {
        
        var speed = parseInt(getStyle( obj, attr )) + dir;            // 步長
        
        if ( speed > target && dir > 0 ||  speed < target && dir < 0  ) {
            speed = target;
        }
        
        obj.style[attr] = speed + 'px';
        
        if ( speed == target ) {
            clearInterval( obj.timer );
            
            /*
            if ( endFn ) {
                endFn();
            }
            */
            endFn && endFn();
            
        }
        
    }, 30);
}

function getStyle ( obj, attr ) { return obj.currentStyle?obj.currentStyle[attr] : getComputedStyle( obj )[attr]; }
</script>

</body>
</html>
View Code

抖動的函數封裝

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>無標題文檔</title>
<style>
img { width:100px; height:100px; position:absolute; top:200px; }
</style>
<script>

function getStyle ( obj, attr ) { return obj.currentStyle?obj.currentStyle[attr] : getComputedStyle( obj )[attr]; }

function shake ( obj, attr, endFn ) {
    
    var pos = parseInt( getStyle(obj, attr) );            // 有隱患的
    
    var arr = [];            // 20, -20, 18, -18 ..... 0
    var num = 0;
    var timer = null;
        
    for ( var i=20; i>0; i-=2 ) {
        arr.push( i, -i );
    }
    arr.push(0);
        
    clearInterval( obj.shake );
    obj.shake = setInterval(function (){
        obj.style[attr] = pos + arr[num] + 'px';
        num++;
        if ( num === arr.length ) {
            clearInterval( obj.shake );
            endFn && endFn();
        }
    }, 50);
}

window.onload = function () {
    var aImg = document.getElementsByTagName('img');
    
    for ( var i=0; i<aImg.length; i++ ) {
        aImg[i].style.left = 80+i*110 + 'px';
        
        aImg[i].onmouseover = function () {
            shake( this, 'top' );
        };
    }
};
</script>

</head>

<body>

<img src="img/1.jpg" />
<img src="img/2.jpg" />
<img src="img/3.jpg" />
<img src="img/4.jpg" />
<img src="img/5.jpg" />
<img src="img/6.jpg" />
<img src="img/7.jpg" />
<img src="img/8.jpg" />

</body>
</html>
View Code

 

第10課:日期對象、時鍾倒計時

Date對象參數

  • 數字形式:new Date(2013, 4 , 1 , 9 , 48 , 12); //年月日時分秒,注意月是從0開始算的。

 

  • var iNow = new Date();
    var iNew = new Date(2014, 10, 26, 21, 56, 0);
    var t = Math.floor((iNew - iNow)/1000); 
    var str = Math.floor(t/86400) + '天' +  Math.floor(t%86400/3600) + '時' + Math.floor(t%86400%3600/60) + '分' +  t%60 + '秒';

     

  • 天:Math.floor(t/86400)
  • 時:Math.floor(t%86400/3600)
  • 分:Math.floor(t%86400%3600/60)
  • 秒:t%60

  • 字符串形式:new Date(‘June 10, 2013 12:12:12’);
  • var iNow = new Date();
    var iNew = new Date('November 10, 2013 21:56:0');
    var t = Math.floor((iNew - iNow)/1000); 
    var str = Math.floor(t/86400) + '天' +  Math.floor(t%86400/3600) + '時' + Math.floor(t%86400%3600/60) + '分' +  t%60 + '秒';

     

時間戳

getTime(); 返回從1970年1月1日0點0分0秒0毫秒到現在的毫秒數

第11課:字符串、查找高亮顯示

字符串獲取類、封裝檢測數字的方法

  • .length 空格也算長度
  • .charAt() 找到子字符串。括號中什么也不寫,默認找第0個。如果超過字符串長度減1,則返回空
  • .charCodeAt() 得到指定子字符的unicode編碼。括號中什么也不寫,默認找到第0個字符的unicode值,括號中最小為0,最大為字符串長度減1
  • String.fromCharCode(); 根據字符編碼,返回一個字符。例如String.fromCharCode(22937);返回的是“妙”字;要得到多個字符,可以用逗號將不同字符編碼隔開,例如:String.fromCharCode(22937, 21916);返回的就是“妙味”兩個字。0~9 => 48~57;a~z => 97~122;A~Z => 65~90 
var str = '妙味課堂';
//alert( str.length );//4
//alert( str.charAt() );//妙

//alert( str.charCodeAt() );            // 22937
//alert( str.charCodeAt(1) );        // 21619

//alert( str.charCodeAt() );            // 0~9  48~57            a~z    97~122            A~Z   65~90

alert( String.fromCharCode(22937, 21619) );//妙味
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>檢測輸入的是數字</title>
</head>

<body>

<input type="text" />
<input type="button" value="檢測" />

<script>

// alert( detectNum('123456') );

var aInp = document.getElementsByTagName('input');

aInp[1].onclick = function () {
    
    var val = aInp[0].value;
    
    if ( detectNum(val) ) {
        alert( '恭喜,'+ val +'全是數字' );
    } else {
        alert('輸入有誤');
    }
};

function detectNum ( str ) {
    var n = 0;
    for ( var i=0; i<str.length; i++ ) {
        n = str.charCodeAt(i);
        if ( n<48 || n>57 )return false;
    }
    return true;
}

</script>

</body>
</html>
View Code

indexOf、lastIndexOf

  • .indexOf() 返回某個字符或字符串在整個字符串中的位置 str.indexOf(‘m’, 5)代表在str字符串中的第5位開始往后找字符m的位置。如果用indexOf()來找,找不到,則返回-1。從左往右找。如果第二個參數為負數,則默認當成0來處理。
  • .lastIndexOf() 從右往前找,也可以帶數字參數,表示從哪里開始往前找。

 

var str = 'www.miaov.com/2013ww';
for ( var i=0; i<str.length; i++ ) {
    if ( str.charAt(i) === 'a' ) {
    //    alert(i);//6
    }
}
 //alert( str.indexOf('a') );//6
 //alert( str.indexOf('a', 5) );//6
// alert( str.indexOf('X') );                    // -1 表示沒找到

alert( str.indexOf('2013', 2) ); //14

var str = '妙味課堂是';

 
         

str.indexOf('妙味', 2) // 從左往右找
alert( str.lastIndexOf('堂',4) );//3

 
         

// 如果第2個值為負數,默認當成0來處理

 
//字符串比較   比較第一位的編碼值
 alert( 'a'.charCodeAt() );//97
 alert( '1' > '2' ); //false
 alert( 'cbbbbb' > 'b' );//true
 alert( '10000' > '2' ); //false

比較類、截取類

  • 字符串的大小比較,比較的就是字符串第0位的字符的unicode編碼

  • .substring(n, m) 截取從第n位起,到m位結束的字符。如果沒有m,就默認截取到最后一位。str.substring(2, 0);和str.substring(0, 2);的結果是一樣的。substring可以檢測里面兩個參數的大小,如果后面的參數小於前面的參數,它就把這兩個參數自動顛倒過來。如果括號里面什么參數都沒有,就相當於從0位截取到最后一位,也就是整個字符串。如果參數中有負數的話,就當做0處理。
  • .slice(n, m) str.slice(0, 2)和str.slide(2, 0)結果不一樣。后者找不到結果,因為.slice()方法,不會判斷里面參數的大小並交換參數位置。str.slice(-2);截取的是從最后一位截取到倒數第二位。-1代表的是最后一位字符串。str.slice(-4, -2);截取的是倒數第四位到倒數第二位的字符串。
var str = '妙味課堂是一支獨具特色的IT培訓團隊';

 alert( str.substring(0,2)  ); //妙味 
alert( str.substring(2,0) );    //妙味             // 可以檢測兩個數,大的往后扔,小的往前扔
alert( str.substring(-3, 2) );    //妙味        // -3 當成0處理
 alert( str.substring(2, -3) );    //妙味    

alert( str.slice( 2, 0 ) );    //空            // 不交換位置
alert( str.slice( -4, -2 ) );    //培訓            // 負數從后面倒着往前數~

字符串操作總結

var str = '妙味課堂-WWW.miaov.com';

str.charAt(1); //
str.charCodeAt(1); //21619
String.fromCharCode(22937, 21619); //妙味

str.indexOf('m', 3); //9
str.lastIndexOf('o'); //16

'1000' < '2' //true
'1000' > 2 //true

str.substring(0, 4); //妙味課堂
str.slice(-3); //'com'

str.toUpperCase(); //'妙味課堂-WWW.MIAOV.COM'
str.toLowerCase(); //'妙味課堂-www.miaov.com'

str.split('.', 2); //['秒微課堂-www', 'miaov']

var arr = ['www', 'miaov', 'com'];
arr.join('.'); //'www.miaov.com'

 

第12課:數組隨機、數組去重

json數據格式及語法

var json = { name: 'leo', age: 32};
alert(json.name);

var imgData = { 
    url: ['img/1.png', 'img/2.png'],
    text: ['圖片一', '圖片二']
};
alert(imgData.url[1]);

var json2 = { 'name': 'miaov' }; //推薦的安全格式的寫法
alert(json2.name);
alert(json2['name']);
json2.name = 'abc';
json2['name'] = '妙味'; //注意中括號里面要用引號

var arr = [{'name': 'TM', 'age': 23}, {'name': 'leo', 'age': 32}];
alert(arr[0].name);

for-in循環,遍歷json

var json4 = { 'name': 'miaov', 'age': 3, 'fun': '前端開發'};
for(var attr in json4){
    alert(attr);
    alert(json4[attr]);
}

var json5 = { 
    url: ['img/1.png', 'img/2.png'],
    text: ['圖片一', '圖片二']
};

for(var attr in json5) {
    for(var i=0; i<json5[attr].length; i++){
        alert(json5[attr][i]);
    }
}

for-in也可以遍歷對象屬性:

var str = '';
var num = 0;
for(var attr in window){
    str += num + '. ' + attr + ' : ' + window[attr] + '<br/>';
    num ++;
}
document.body.innerHTML = str;

數組也可以用for-in來遍歷:

var arr = ['a', 'b', 'c'];
for(var i in arr){
    alert(arr[i]);
}

清空數組和清空數組效率問題

// var arr = [1, 2, 3];
// var arr = new Array(1, 2, 3);

var arr = new Array(4);
alert(arr.length); // 4 在new Array()里面寫了一個數字,就是定義了arr的長度



var arr = [1, 2, 3];
arr.length = 1; //數組的length屬性是可寫的
alert(arr);



ar arr = [1, 2, 3];
arr.length = 0; //快速清空數組arr
或
arr = []; //通過重新賦值來清空數組,效率更高


var str = 'aaaaa';
str.length = 1;
alert(str); // 'aaaaa'
//字符串的length屬性不可寫,但是數組的length屬性可寫

 

數組的操作

添加

  • push方法:arr.push(); 往數組最后一位添加內容。.push()方法是有返回值的,返回的是數組新的長度
  • unshift方法:arr.unshift(); 往數組的最前面添加內容,返回值為數組新的長度(IE6、7不支持unshift的返回值)

刪除

  • pop方法:arr.pop(); 刪除數組的最后一個,返回值是被扔掉的值
  • shift方法:arr.shift(); 刪除數組的第一個,返回值是被扔掉的值

小技巧

ar arr = ['TM', '鍾毅', '張森', '杜鵬', 'Leo'];
arr.unshift(arr.pop()); //數組變為:['Leo', '鍾毅', '張森', '杜鵬', 'TM']
或
arr.push(arr.shift()); //數組變為:['鍾毅', '張森', '杜鵬', 'Leo', 'TM']

splice方法

  • splice方法有刪除、替換、添加三種功能
var arr = ['TM', '鍾毅', '張森', '杜鵬', 'Leo'];
//刪除
//arr.splice(0, 1); //刪掉第0位,刪1個。兩個參數第一個是從第幾位開始,第二個是刪掉幾個。splice刪除的時候有返回值,返回的是被刪除的內容
//替換
//arr.splice(0, 1, '莫濤'); //替換第0位,替換1個,替換為'莫濤'。返回的還是刪除的東西
//添加
arr.splice(1, 0, '李賢'); //在第1位那里,刪除0個,添加了一個'李賢'到了第1位,'鍾毅'就變成了arr[2]了。后面也可以添加多個。如果splice刪除了0個,那么就沒有返回值。

數組去重

var arr = [1, 2, 2, 4, 2];
for ( var i=0; i<arr.length; i++ ) {
    for ( var j = i+1; j<arr.length; j++) {
        if( arr[i]==arr[j] ){
            arr.splice( j, 1 );
            j--;
        }
    }
}

sort排序

var arr = ['c', 'd', 'a', 'e'];
arr.sort(); // 'a', 'c', 'd', 'e' 按照unicode編碼排序

var arr2 = [4, 3, 5, 76, 2, 0, 8];
arr2.sort(); // 0, 2, 3, 4, 5, 76, 8 sort默認是將數組中的每一個按照字符串來排序的,因此出現了76排在8前面的情況

// arr2. sort(function( a, b ){
    return a - b; //如果a-b返回正數,就a、b兩個數字換個序。如果a-b是負數,就不換序
}) //返回數字從小到大 0, 2, 3, 4, 5, 8, 76

// arr2. sort(function( a, b ){
    return b - a;
}) //返回數字從大到小 76,, 8, 5, 4, 3, 2, 0


var arrWidth = [ '345px', '23px', '10px', '1000px' ];

arrWidth.sort(function ( a, b ) {
    
    return parseInt(a) - parseInt(b);
});

alert( arrWidth ); //10px,23px,345px,1000px

 

其他排序方法:

  • 快速排序法
  • 希爾排序法
  • 冒泡排序法
  • 歸並排序法
  • 選擇排序法
  • 插入排序法
var arrWidth = ['345px', '23px', '10px', '1000px'];
arrWidth.sort(function(a, b){
    return parseInt(a) - parseInt(b);
}); // ['10px', '23px', '345px', '1000px']

隨機排序

var arr = [1, 2, 3, 4, 5, 6, 7, 8];
arr.sort(function(a, b){
    return Math.random() - 0.5;
});

隨機數以及隨機公式推理過程

Math.random(); 返回0~1之間隨機的一個數

如果想要隨機返回0和1之間的一個整數,可以用四舍五入的方法:

Math.round(Math.random()); //注意,這里不能用Math.floor

如果想要返回0~10之間的一個隨機數:

Math.round(Math.random() * 10); //返回0~10之間的隨機整數

返回從20~100之間的一個隨機數:

Math.round( Math.random()*80 + 20 ); //返回5~10之間的隨機整數

如果想要返回一個x到y之間的整數,可以寫成:

Math.round( Math.random() * (y - x) + x );

返回0~x的整數,可以寫成

Math.round( Math.random() * x );

返回1~x的整數,可以寫成

Math.ceil( Math.random() * x ); //Math.ceil()是向上取整

concat方法

concat方法用於連接數組。

var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = [7, 8, 9];

arr1.concat(arr2); //[1, 2, 3, 4, 5, 6] 新數組與原來數組沒什么關系。
arr1.concat(arr2, arr3); //[1, 2, 3, 4, 5, 6, 7, 8, 9]

reverse方法

reverse方法是顛倒數組中的位置,會改變原數組

var arr1 = [1, 2, 3];
arr1.reverse();
alert(arr1); // [3, 2, 1]
var str = 'abcdef';
alert(str.split('').reverse().join('')); //'fedcba'

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM