那些年,我們應該瞭解的 JavaScript 小知識 - 物件, 數字, 字串, 陣列, 迴圈

JavaScript 是需要被瞭解

JavaScript 是一種非常方便就能上手及使用的程式語言,但真正瞭解 JavaScript 就不多了。借由 HTML5 的推助,JavaScript 再一次站上主角,第一次是 XMLHttpRequest 的 AJAX 應用,而 HTML5 滿滿的 API 全部都必須使用 JavaScript 撰寫來實現。我們必須更進一瞭解 JavaScript,而不只是簡單帶過。

這一篇會介紹 JavaScript 裡一些小知識,包含物件,數字,字串,陣列,迴圈等。

萬物皆物件

在 JavaScript 的世界裡,除了非常少數核心部分,廣義而言,可以說萬物階物件(Object),我們常看和不常看的型態都是一種物件,例如:

  • Number (數字是物件)
  • String (字串是物件)
  • Boolean (布林是物件)
  • Object (物件是物件)
    • Function (函式是物件)
    • Array (陣列是物件)
    • Date (日期是物件)
    • regExp (正規表達式是物件)
  • Null (空是物件)
  • Undefined (未定義是物件)
  • Error (錯誤是物件)

好多物件,這和我們學習的正規程式語言有很大差異,但沒關係,當你在學習 JavaScript 時,如果有卡卡的,看不懂的地方,回想這句話:「萬物階物件」,用物件的角度來看事情,先不要管它是個什麼東西,它就物件,很多時候問題會簡單很多。

數字小知識

第一件事,在 JavaScript 中沒有整數這件事。在規範中 JavaScript 數字是一個「雙精確度 64位元格式 IEEE745 值(double-precision 64-bit binary format IEEE 754 value)」,所以在做小數點大數運算時必須小心。例如,「0.1 + 0.2」或「一個 16位數或超過 16位數」的數值。

第二件事,在進行 parseInt() 函式將字串轉成整數時,一定要指定第二個參數,第二個參數指定進位數

var a = 0.1 + 0.2;
document.writeln(a); // 0.30000000000000004

var b = 9999999999999998;
document.writeln(b);

var c = 9999999999999999;
document.writeln(c); // 10000000000000000 

var d = parseInt("014");
document.writeln(d); // 12,果然有問題

var e = parseInt("014", 10);
document.writeln(e); // 14,你在貪污呀,抓到了吧

var f = parseInt("014", 16);
document.writeln(f); // 20,這是洗錢手法之一

以上程式碼純屬程式,沒有其他用意。@_@

字串小知識

JavaScript 裡的每個字元都會序列化為 Unicode字元,即會以一個 16位元的字數來表示。這可以讓需要國際化的不用特別擔心編碼問題。你寫什麼(中文、韓文、日文、印度文…),網頁裡就是顯示什麼。

document.writeln("我愛妳");
document.writeln("我爱妳");
document.writeln("私はあなたを愛して");

null 與 undefined 小知識

null(空),是一種無數值的情況。undefined(未定義),是一種未初始化的情況。

var a; // undefined
var b = null; // null

a 是未定義;b 是空。你宣告一個變數但未指定值,那是未定義不是空。空是一種狀態。我們常在 for 迴圈內使用 return 來跳離迴圈,return 未指定值,那是未定義不是空。

&& 與 || 小知識

&& (and) 與 || (or) 運算子在判斷條件時,第二個條件是否執行依第一個條件來決定。這用來存取一個物件的屬性前檢查物件是否為空非常有用。

// 跨瀏覽器處理
var event = window || window.event;

// 1. person 物件不為 null
// 2. 取出 person.getName() 的值
var name = person && person.getName();

// 1. person 物件為 null
// 2. 指定 "無" 為預設值
var englishName = person || "無";

物件小知識

JavaScript 裡的物件是字典(name-value pair),name 的部分必須是字串, value 可以是任何 JavaScript 的值。JavaScript 的值就是好玩的地方,因為可放任何 JavaScript 的值,所以物件裡可以放物件,還記得第一點嗎,萬物皆物件,到了這裡可以再加一句,萬物皆可放。

// 意義上,objA 與 objB 是相等,都是產生一個空物件。
// 實務上都會使用實體語法,尤其是在物件及陣列
var objA = new Object();
var objB = {}; // 實體語法(object literal)

// 意義上,兩種存取語法是相同的
objB.boyName = "Bruce"; // 存
var manName = objB.boyName; // 取

objB["girlName"] = "Sherry"; // 存
var womanName = objB["girlName"]; // 取

第二種用法有個優點,屬性的名稱是以字串提供,當你將屬性設定為 JavaScript 關鍵字時,第二種存取方法不會出錯,第一種 . (點)物件存取是不可以使用 JavaScript 關鍵字。

// 直接進行屬性初始化
// 格式 name : value
var food = {
    name: "紅蘿蔔",
    "for": "Happy",
    details: { // 物件裡的物件
        color : "red",
        price : 23,  
    }
};

// 一層一層存取即可
var foodColor = food.details.color;

name,"for" 是屬性,for 是關鍵字,用 "for" 表示它是單純字串,details 是個物件,color,price 是屬性。實務上,我們會把物件屬性名稱都用字串表示,這在未來撰寫 JSON 相關應用時,可以用一致的習慣來撰寫,這裡是為了展示物件範例才未加上。

陣列小知識

陣列的運作和物件很像。

var arrA = new Array();
var arrB = []; // 實體語法

{} 與 [] 都是實體語法,實務上我們也大多使用實體語法是撰寫 JavaScript 程式碼。陣列好玩的地方在它有個物件沒有的屬性 length (長度)。

// 直接進行陣列初始化
var arrC = ["Dog", "Cat", "Fish", "Bird"];
console.log(arrC.length); // 4

var arrD = ["Dog", "Cat", "Fish", "Bird"];
arrD[14] = "Money"; // 14 說給我錢,其他免談
arrD.length; // 15

第二範例的 arrD 讓我們瞭解二件事,一是 JavaScript 的陣列隨時可變,而且會自動調整至 index 指定的大小。二是 length 的回傳值是最高 Index 值加一。JavaScript 的索引是由 0 開始,length 是回傳項目個數,它不管項目是否有值。如果我們查取一個不存在的陣列,得到會是未定義(undefined),說到這裡是否瞭解 null 和 undefinded 差異了。

console.log(typeof(arrD[33])); // undefined

前面我們瞭解到 length 的回傳值是最高 Index 值加一,利用此特性,我們可以在陣列的最尾端加入項目:

arrD[arrD.length] = "Ant"; // 相等 arrD.push("Ant");

這可以說是最安全有順序加入陣列的方式。

陣列迴圈處理小知識

我們經常使用迴圈來取陣列的值。

for (var i=0; i < arrD.length; i++){
    // Do something
}

注意這裡「i < arrD.length」,程式每判斷一次就必須去取出 arrD.length 一次,這不是很呆嗎?應該這樣做:

for (var i=0, len=arrD.length; i<len ; i++){
    // Do something
}

我們先取出 arrD.length 的值讓它成為 len 變數,接下來只要拿 len 來進行判斷,程式馬上加速。另外還可以再加以變型:

for (var i=0, value; value = arrD[i]; i++){
    // Do something
}

這是利用 for 迴圈執行前會先測試條件( value = arrD[i] )是否為真,成功,便執行迴圈。執行順序為:

  1. 初始變數
  2. 測試 arrD[i] 是否有值
  3. arrD[i] 有值,進行取值及設定給變數 value,執行 for 迴圈
  4. arrD[i] 無值,離開 for 迴圈

第二步是重點,它的使用比第二種 len=arrD.length 更直接也更快,第二種方式因是必須在 for 迴圈內再進行一次取值處理的動作。不過此技巧有個小限制,你必須非常確定陣列裡不會有「假值」,例如,可能含有數字 0、空字串、陣列裡的物件、DOM 節點 … 有的話,還是使用第二種來處理。

1 則留言:

  1. If the string begins with "0", the radix is 8 (octal). This feature of parseInt() functionis deprecated

    回覆刪除

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。