JavaScript學習(1):基礎


  這篇文章里,我們來聊一些JavaScript的基礎知識。

  1. 如何運行JavaScript?

  JavaScript是一種解釋型的語言,它不需要提前編譯。通常情況下,JavaScript會放在網頁中,在瀏覽器中運行。我們也可以找到一些在線的可以運行JavaScript的平台,當然我們也可以在Firefox或者Chrome里運行。

  我在網上找到了一個可以在線運行的網站:runjs,文章中的代碼都是在該網站上運行的。

  實際上,我們可以在本地創建一個簡單的網頁,然后通過編輯網頁的方式來測試JavaScript代碼。

  下面是代碼的基本運行結構:

 1 $(document).ready(
 2     function(){
 3         //在這里調用外面的函數
 4         print(add(1,1));
 5     });
 6 
 7 //封裝document.write
 8 function print(obj){
 9     document.write(obj);
10     document.write("<br>");
11 }
12 
13 //簡單的示例方法
14 function add(left, right){
15     return left + right;
16 }

  2. JavaScript基本數據類型

  JavaScript的基本數據類型包括6種:number/string/boolean/object/function/undefined。

  2.1 number類型

  number類型用來存儲數值,它描述的是64位的浮點型數值。但Javascript並不能表示0-2e64之間的所有數值,因為它還需要表示非整數,包括復數、分數等。對於64位來說,需要使用11位來存儲數字的小數部分,使用1位來表示正負,所以JavaScript實際上可以表示-2e52到2e52之間的值。

  2.2 string類型

  string類型用來表示文本,可以使用單引號或者雙引號來包括文本,任何放在引號內的符號,都會被認為是string,但對於特殊符號,可能需要轉義處理。

  2.3 boolean類型

  boolean類型只包括兩個值:true和false。我們可以在程序中使用各種boolean表達式來得到true或者false,從而實現不同的業務分支處理。

  我們可以在表達式中包含多個條件,條件之間可以是與或非的關系,在計算時,優先級如下:||的優先級最低,其次是&&,然后是比較運算符,最后是其他運算符(例如!)。

  和其他許多語言一樣,對於&&來說,當前面的條件為false時,后面的條件不再計算,對於||來說,當前面的條件為true時,后面的條件不再計算。

  來看下面的例子:

 1 function conditionTest(){
 2     var a = 1;
 3     var b = 1;
 4     var c = {"key":"old"};
 5     print(c["key"]);
 6     if (a==1) print("a = 1");
 7     if (a==1 && b==1) print("a == 1 && b == 1");
 8     if (a==1 || changeValue(c)) print(c["key"]);
 9     if (a==1 && changeValue(c)) print(c["key"]);
10 }
11 
12 function changeValue(obj){
13     obj["key"] = "changed";
14     return true;
15 }

  它的輸出結果如下:

old
a = 1
a == 1 && b == 1
old
changed

  可以看出,在使用||時,沒有調用changeValue方法。

  2.4 undefined類型

  當我們聲明了一個變量,但是沒有對其賦值時,它就是undefined的,就像下面這樣

1 var b;
2 print(b);

  在Javascript中,還有一個和undefined類似的值:null。undefined表示“變量已聲明但是沒有復制”,null表示“變量已賦值但為空”,需要注意的是undefined==null的值為true。

  2.5 類型轉換

  我們在上面提到了undefined == null的值是true,但我們使用typeof操作時可以發現,null是object類型,這說明在比較的過程中,發生了類型轉換。

  類型轉換是指將一種類型的值轉換成另外一種類型的值。我們使用==進行比較時,會有類型轉換,我們可以使用===來禁止類型轉換。

  來看下面的例子:

 1 function convertTypeTest(){
 2     var a = 1;
 3     var b = "1";
 4     print ("a:" + a);
 5     print ("b:" + b);
 6     print ("type of a:" + typeof a);
 7     print ("type of b:" + typeof b);
 8     print ("a==b:" + (a == b));
 9     print ("a===b:" + (a === b));
10     print ("a===Number(b):" + (a === Number(b)));
11     print ("String(a)===b:" + (String(a) === b));
12     print ("type of undefined:" + typeof undefined);
13     print ("type of null:" + typeof null);
14     print ("undefined==null:" + (undefined == null));
15     print ("undefined===null:" + (undefined === null));
16 }

  輸出結果如下:

a:1
b:1
type of a:number
type of b:string
a==b:true
a===b:false
a===Number(b):true
String(a)===b:true type of undefined:undefined type of null:object
undefined==null:true
undefined===null:false

  可以很明顯看到==和===的區別。

  3. JavaScript基本邏輯流程控制

  和大部分編程語言一樣,JavaScript的邏輯控制基本上也是分為順序、循環和條件。

  3.1 順序

  上面給出的各個示例代碼都是順序執行的。

  3.2 循環

  JavaScript使用for、while來完成循環,下面是一個從1加到100的例子:

1 function loopTest(){
2     var start = 1;
3     var end = 100;
4     var result = 0;
5     for (i = start; i <= end; i++){
6         result = result + i;
7     }
8     print (result);
9 }

  3.3 條件

  JavaScript使用if、switch來完成條件判斷,下面是一個關於分數分類的例子:

1 function gradeLevel(grade){
2     var level;
3     if (grade <= 100 && grade >= 90) level="優秀";
4     else if (grade >= 80) level = "良好";
5     else if (grade >= 60) level = "及格";
6     else level="不及格";
7     print(level);
8 }

  4. 函數

  函數是JavaScript很重要的一部分,它是模塊化的基礎。我們在上面的示例中已經定義了很多函數,接下來我們看一些更有意思的東西。

  4.1 變量的作用域

  在JavaScript中,變量的作用域可以分為全局作用域和局部作用域。在函數體內部聲明的變量屬於局部變量。

  來看下面的例子:

 1 var a = 1;
 2 
 3 function change1(){
 4     a=2;
 5 }
 6 
 7 function change2(){
 8     var a =3;
 9 }
10 
11 function print(obj){
12     document.write(obj);
13     document.write("<br>");
14 }
15 
16 
17 //調用順序
18     print(a);
19     change1();
20     print(a);
21     change2();
22     print(a);

  從運行結果可以看出,change1修改了全局變量a的值,但change2沒有修改,這是因為在change2中定義了一個同名的局部變量,所以在該方法體內發生的操作只作用在局部變量上。

  4.2 嵌套函數

  JavaScript允許在函數體內嵌套函數,這樣從某種程度上,可以控制一些變量在某些函數內共享。

  下面是一個實現四則運算的例子:

 1 function operation(left,right,op){
 2     function add(){
 3         return left + right;
 4     }
 5     function minus(){
 6         return left - right;
 7     }
 8     function multiple(){
 9         return left*right;
10     }
11     function divide(){
12         return left/right;
13     }
14     if (op=="+") print (add());
15     else if (op=="-") print (minus());
16     else if (op=="*") print (multiple());
17     else if (op=="/") print (divide());
18     else print ("Invalid operation.");
19 }

  對於示例代碼,我們可以發現,內嵌函數可以訪問外部函數的參數、全局變量等。

  在調用函數時,通常是沒有辦法直接訪問內嵌函數的。

  4.3 函數調用的機制

  JavaScript使用棧和上下文的機制來調用函數,我們可以將JavaScript執行時的每一行代碼的順序看做是上下文,並且使用棧來存儲上下文。

  當我們調用一個方法時,在調用前,棧會保存當前上下文,然后調用函數,在調用結束后,棧會從之前保存過的上下文開始繼續執行。

  如果上下文增長過快,會導致堆棧溢出,例如當我們在A方法中調用B方法,然后在B方法中調用A方法,這種循環調用的方式很容易就將堆棧搞壞了。

  4.4 函數作為值的處理

  在JavaScript中,函數也是一種值,這是和其他語言不太一樣的。

  來看下面的代碼:

1         var a=false;
2         function test(){
3             print("test");
4         }
5         
6         (a||test)();
7         
8         var b=test;
9         b();

  如果要理解“函數都是值”的意思,我們可以從某種程度上認為b是一個函數指針,它指向了test函數。

  4.5 閉包

  JavaScript中的閉包是指函數的返回值是一個函數,並且返回值函數使用了外部函數的變量(參數或者局部變量)。

  對於嵌套函數來講,它可以訪問外部函數的參數或者局部變量,示例如下:

 1         function foo(x){
 2             var y=1;
 3             function bar(z){
 4                 y=y+1;
 5                 print(x+y+z);
 6             }
 7             bar(1);
 8         }
 9 
10         foo(1);

  在這里,嵌套函數bar訪問了外部函數foo的參數x及局部變量y,並且對y有加1的操作,但這不叫閉包,我們多次調用foo(1),並沒有使得y遞增。

  下面才是閉包:

 1         function foo(x){
 2             var y =1;
 3             return function(z){
 4                 y = y+1;
 5                 print(x+y+z);
 6             }
 7         }
 8         
 9         var bar=foo(1);
10         bar(1);

  我們可以看到上面代碼中foo的返回值本身就是一個匿名函數,如果我們多次調用bar(1),可以發現foo函數的局部變量y的值是一直在遞增。

  閉包在實際的應用中,一般是用來封裝對復雜數據結構的各種操作,從而對外提供簡單易用的接口,用戶在使用時不用太關心閉包內部的實現細節。

  4.6 函數的可變參數

  JavaScript在調用函數時,並不會限制傳入參數的個數,當傳入參數的個數多於函數定義中參數的個數時,多余的參數會被忽略;當傳入參數的個數小於函數定義中參數的個數時,缺失的參數默認是undefined。

  我們來看下面的例子:

 1 function argumentTest(v1,v2,v3,v4){
 2     print(v1+v2+v3+v4);
 3 }
 4 
 5 //調用方法
 6 argumentTest(1,2,3);
 7 argumentTest(1,2,3,4,5);
 8 
 9 
10 //輸出結果
11 NaN
12 10

  可以看到,當我們給出的參數有缺失時,默認的undefined和其他參數做運算時,返回了NaN。當我們給出的參數有富余時,被自動忽略了。

  在JavaScript中,函數中有默認的一個變量,名為arguments在這里,arguments並不是一個數組,typeof arguments返回的是object),它用來保存所有傳入的參數,我們來看下面的例子:

 1 function argumentTest(v1,v2,v3,v4){
 2     var result=0;
 3     for(var i = 0; i < arguments.length;i++){
 4         result=result+arguments[i];
 5     }
 6     print(result);
 7 }
 8 
 9 //調用方法
10 argumentTest(1,2,3);
11 argumentTest(1,2,3,4,5);
12 
13 //執行結果
14 6
15 15

  這里我們可以看到,無論我們傳入了多少參數,都可以被適當的處理了。


免責聲明!

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



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