JavaScript基礎總結

weixin_34292287發表於2019-01-04

資料型別

在JavaScript中是沒有分整數,浮點數,全部統一都是Number表示,比如字串,布林值和一些常用的運算子。下面總結了一些與Java不一樣的:

  • ==與===
false == 0; // true
false === 0; // false

第一種是==比較,它會自動轉換資料型別再比較,很多時候,會得到非常詭異的結果;
第二種是===比較,它不會自動轉換資料型別,如果資料型別不一致,返回false,如果一致,再比較。
由於JavaScript這個設計缺陷,不要使用==比較,始終堅持使用===比較。

  • NaN
NaN === NaN; // false
isNaN(NaN); // true

NaN這個特殊的Number與所有其他值都不相等,包括它自己,唯一能判斷NaN的方法是通過isNaN()函式。

  • 浮點數的相等比較
1 / 3 === (1 - 2 / 3); // false
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true

這不是JavaScript的設計缺陷。浮點數在運算過程中會產生誤差,因為計算機無法精確表示無限迴圈小數。要比較兩個浮點數是否相等,只能計算它們之差的絕對值,看是否小於某個閾值。

  • null和undefined

null表示一個“空”的值,它和0以及空字串''不同,0是一個數值,''表示長度為0的字串,而null表示“空”。
在其他語言中,也有類似JavaScript的null的表示,例如Java也用null,Swift用nil,Python用None表示。但是,在JavaScript中,還有一個和null類似的undefined,它表示“未定義”。
JavaScript的設計者希望用null表示一個空的值,而undefined表示值未定義。事實證明,這並沒有什麼卵用,區分兩者的意義不大。大多數情況下,我們都應該用null。undefined僅僅在判斷函式引數是否傳遞的情況下有用。

  • 陣列
    陣列是一組按順序排列的集合,集合的每個值稱為元素。JavaScript的陣列可以包括任意資料型別:
[1, 2, 3.14, 'Hello', null, true];

另一種建立陣列的方法是通過Array()函式實現:

new Array(1, 2, 3); // 建立了陣列[1, 2, 3]
  • 物件
    JavaScript的物件是一組由鍵-值組成的無序集合,JavaScript物件的鍵都是字串型別,值可以是任意資料型別。上述person物件一共定義了6個鍵值對,其中每個鍵又稱為物件的屬性,例如,person的name屬性為'Bob',zipcode屬性為null。要獲取一個物件的屬性,我們用物件變數.屬性名的方式:
var person = {
    name: 'Bob',
    age: 20,
    tags: ['js', 'web', 'mobile'],
    city: 'Beijing',
    hasCar: true,
    zipcode: null
};
person.name; // 'Bob'
person.zipcode; // null
  • 變數
    申明一個變數用var語句,同一個變數可以反覆賦值,而且可以是不同型別的變數,但是要注意只能用var申明一次
var a = 123; // a的值是整數123
a = 'ABC'; // a變為字串
  • 字串
    由於多行字串用\n寫起來比較費事,所以最新的ES6標準新增了一種多行字串的表示方法,用反引號 ... 表示:
`這是一個
多行
字串`;

如果有很多變數需要連線,用+號就比較麻煩。ES6新增了一種模板字串,表示方法和上面的多行字串一樣,但是它會自動替換字串中的變數:

var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}歲了!`;
alert(message);

要獲取字串某個指定位置的字元,使用類似Array的下標操作,索引號從0開始,需要特別注意的是,字串是不可變的,如果對字串的某個索引賦值,不會有任何錯誤,但是,也沒有任何效果:

var s = 'Hello, world!';
s[0]; // 'H'
s[6]; // ' '
s[7]; // 'w'
s[12]; // '!'
s[13]; // undefined 超出範圍的索引不會報錯,但一律返回undefined

var s = 'Test';
s[0] = 'X';
alert(s); // s仍然為'Test'

如果需要將多個字串連線起來,在Java中我們可以使用+號連線,在JavaScript中也是同樣可以的,但是如果有很多變數需要連線,用+號就比較麻煩。ES6新增了一種模板字串,表示方法和上面的多行字串一樣,但是它會自動替換字串中的變數:

var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}歲了!`;
alert(message);
  • 陣列
    JavaScript的Array可以包含任意資料型別,並通過索引來訪問每個元素。比如:
var arr = [1, 2, 3.14, 'Hello', null, true];

請注意,如果通過索引賦值時,索引超過了範圍,同樣會引起Array大小的變化:

var arr = [1, 2, 3];
arr[5] = 'x';
arr; // arr變為[1, 2, 3, undefined, undefined, 'x']

slice()就是對應String的substring()版本,它擷取Array的部分元素,然後返回一個新的Array,注意到slice()的起止引數包括開始索引,不包括結束索引。如果不給slice()傳遞任何引數,它就會從頭到尾擷取所有元素。利用這一點,我們可以很容易地複製一個Array:

var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
var aCopy = arr.slice();
aCopy; // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
aCopy === arr; // false

push()向Array的末尾新增若干元素,pop()則把Array的最後一個元素刪除掉,如果要往Array的頭部新增若干元素,使用unshift()方法,shift()方法則把Array的第一個元素刪掉,

var arr = [1, 2];
arr.push('A', 'B'); // 返回Array新的長度: 4
arr; // [1, 2, 'A', 'B']
arr.pop(); // pop()返回'B'
arr; // [1, 2, 'A']
arr.pop(); arr.pop(); arr.pop(); // 連續pop 3次
arr; // []
arr.pop(); // 空陣列繼續pop不會報錯,而是返回undefined
arr; // []

arr.unshift('A', 'B'); // 返回Array新的長度: 4
arr; // ['A', 'B', 1, 2]
arr.shift(); // 'A'
arr; // ['B', 1, 2]
arr.shift(); arr.shift(); arr.shift(); // 連續shift 3次
arr; // []
arr.shift(); // 空陣列繼續shift不會報錯,而是返回undefined
arr; // []

splice()方法是修改Array的“萬能方法”,它可以從指定的索引開始刪除若干元素,然後再從該位置新增若干元素:

var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 從索引2開始刪除3個元素,然後再新增兩個元素:
arr.splice(2, 3, 'Google', 'Facebook'); // 返回刪除的元素 ['Yahoo', 'AOL', 'Excite']
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 只刪除,不新增:
arr.splice(2, 2); // ['Google', 'Facebook']
arr; // ['Microsoft', 'Apple', 'Oracle']
// 只新增,不刪除:
arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因為沒有刪除任何元素
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']

concat()方法把當前的Array和另一個Array連線起來,並返回一個新的Array,請注意,concat()方法並沒有修改當前Array,而是返回了一個新的Array。實際上,concat()方法可以接收任意個元素和Array,並且自動把Array拆開,然後全部新增到新的Array裡:

var arr = ['A', 'B', 'C'];
var added = arr.concat([1, 2, 3]);
added; // ['A', 'B', 'C', 1, 2, 3]
arr; // ['A', 'B', 'C']

join()方法是一個非常實用的方法,它把當前Array的每個元素都用指定的字串連線起來,然後返回連線後的字串,如果Array的元素不是字串,將自動轉換為字串後再連線。

var arr = ['A', 'B', 'C', 1, 2, 3];
arr.join('-'); // 'A-B-C-1-2-3'
  • 物件型別
    JavaScript用一個{...}表示一個物件,鍵值對以xxx: xxx形式申明,用,隔開。注意,最後一個鍵值對不需要在末尾加,,如果加了,有的瀏覽器(如低版本的IE)將報錯。
var xiaoming = {
    name: '小明',
    birth: 1990,
    school: 'No.1 Middle School',
    height: 1.70,
    weight: 65,
    score: null
};

由於JavaScript的物件是動態型別,你可以自由地給一個物件新增或刪除屬性:

var xiaoming = {
    name: '小明'
};
xiaoming.age; // undefined
xiaoming.age = 18; // 新增一個age屬性
xiaoming.age; // 18
delete xiaoming.age; // 刪除age屬性
xiaoming.age; // undefined
delete xiaoming['name']; // 刪除name屬性
xiaoming.name; // undefined
delete xiaoming.school; // 刪除一個不存在的school屬性也不會報錯

如果我們要檢測xiaoming是否擁有某一屬性,可以用in操作符,不過要小心,如果in判斷一個屬性存在,這個屬性不一定是xiaoming的,它可能是xiaoming繼承得到的:

var xiaoming = {
    name: '小明',
    birth: 1990,
    school: 'No.1 Middle School',
    height: 1.70,
    weight: 65,
    score: null
};
'name' in xiaoming; // true
'grade' in xiaoming; // false

因為toString定義在object物件中,而所有物件最終都會在原型鏈上指向object,所以xiaoming也擁有toString屬性。要判斷一個屬性是否是xiaoming自身擁有的,而不是繼承得到的,可以用hasOwnProperty()方法:

var xiaoming = {
    name: '小明'
};
xiaoming.hasOwnProperty('name'); // true
xiaoming.hasOwnProperty('toString'); // false

Map和Set
JavaScript的預設物件表示方式{}可以視為其他語言中的Map或Dictionary的資料結構,即一組鍵值對。但是JavaScript的物件有個小問題,就是鍵必須是字串。但實際上Number或者其他資料型別作為鍵也是非常合理的。為了解決這個問題,最新的ES6規範引入了新的資料型別Map。

  • Map
    用JavaScript寫一個Map如下:
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
m.get('Michael'); // 95

var m = new Map(); // 空Map
m.set('Adam', 67); // 新增新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 刪除key 'Adam'
m.get('Adam'); // undefined
  • Set
    Set和Map類似,也是一組key的集合,但不儲存value。由於key不能重複,所以,在Set中,沒有重複的key。要建立一個Set,需要提供一個Array作為輸入,或者直接建立一個空Set:
var s1 = new Set(); // 空Set
var s2 = new Set([1, 2, 3]); // 含1, 2, 3

相關文章