JavaScript奇葩語言特性歸納(持續更新中...)

1. 基本概念

1.1 數據類型

(1)typeof操作符


console.log(typeof null);  // “object”

用typeof操作符去監測null,得到的類型是object。
原因是null被認爲是一個空的對象引用。


function func(){
  // do something
}
console.log(typeof func);  // "function"

function雖然不是6大數據類型中的一種,但卻可以被typeof操作符監測出來。
原因是函數在ECMAScript中是對象,但函數確實有一些特殊的屬性,所以需要用typeof來區分。

(2)Undefined


var message;
console.log(message); // undefined
console.log(answer);  // 報錯

console.log(typeof message);  // undefined
console.log(typeof answer);   // undefined

聲明後未初始化的變量默認值爲undefined,想獲得一個未聲明的變量會報錯,這很好理解。
但是用typeof操作符監測聲明後未初始化的變量和一個未聲明的變量都會得到undefined。雖然這兩種變量從技術角度看有本質區別,但實際上也不可能對它們做任何操作。
所以在聲明變量的時候顯式地初始化是一個好的選擇,這樣監測出undefined就知道是未聲明的變量了。

(3)Null

null表示的是一個空對象指針,所以如果一個變量在之後準備保存對象,那麼初始化的值爲null是最合理的。這樣只要檢查null值就知道是否已經保存了一個對象的引用了。


console.log(undefined == null);  // true

用相等操作符(=)去比較undefined和null會得到true的結果。
原因是undefined實際上是派生自null。[ 這句話我覺得不用理解, 語言就是這麼設計的。 ]

(4)Boolean

ECMAScript中所有的值都有與2個boolean值對應的值:

數據類型 轉換爲true 轉換爲false
Boolean true false
String 任何非空字符 空字符
Number 任何非零數字值 0和NaN
Object 任何對象 null
Undefined n/a(不適用) undefined

(5)Number


var floatNum1 = 1.;    // 解析爲1
var floatNum2 = 10.0;  // 解析爲10

由於保存浮點數值需要的內存空間是保存整數值的兩倍,因此ECMAScript會不失時機地將浮點數值轉換爲整數值。
如果小數點後面沒有跟任何數字,那麼這個數值就可以作爲整數值來保存。


console.log(0.1 + 0.2);  // 0.30000000000000004

浮點數計算不精確。
基於IEEE754數值浮點計算產生誤差,原因是計算機會先把0.1和0.2轉化爲二進制,再把相加的結果轉化爲十進制。在兩次轉化中產生了誤差。


由於內存的限制,ECMAScript並不能保存世界上所有的數值。最小數值爲5e-324,保存在Number.MIN_VALUE中;最大數值爲1.7976931348623157e+308,保存在Number.MAX_VALUE中。如果某次計算的結果得到了一個超出JavaScript數值範圍的值,那麼這個數值將被自動轉換成特殊的infinity具體來說,如果這個數值是負數,則會被轉換成-infinity(負無窮),如果這個數值是正數,則會被轉換成Infinity (正無窮)。
可使用isFinite()函數來確定一個數值是不是又窮的。


console.log(NaN == NaN);  // false

NaN,即非數值(Not a Number)是一個特殊的數值,這個數值用於表示一個本來要返回數值的操作數未返回數值的情況(這樣就不會拋出錯誤了)。
NaN本身有兩個非同尋常的特點:
首先,任何涉及NaN的操作(例如NaN/10)都會返冋NaN,這個特點在多步計算中有可能導致問題。
其次,NaN與任何值都不相等,包括NaN本身。


這裏我們探討一個問題就是任何數據除以0只會返回2種結果:1個是NaN,一個是Infinity。
下面看幾個例子:

console.log(0/0);       // NaN
console.log(true/0);    // Infinity
console.log(false/0);   // NaN
console.log("2222"/0);  // Infinity
console.log(-1/0);      // -Inifinity
console.log(undefined/0);  // NaN
console.log(null/0);    // NaN

從這幾個例子中可以歸納出幾個結論:

  1. 0/0和NaN/0 會得到NaN (例子中false會轉化爲0,undefined會轉化成NaN,null會轉化爲0, 對象會轉化爲NaN[示例中未舉出])
  2. 其他任何轉化爲數字不爲0的值除以0 都會得到Infinity (正值就是Infinity,負值則爲-Infinity)

可用isNaN()函數來判斷這個參數是否“不是數值”。如果這個值不能被轉化成數值,則返回true。

console.log(isNaN(NaN));    // true
console.log(isNaN(10));     // false
console.log(isNaN("10"));   // false
console.log(isNaN("blue")); // true
console.log(isNaN(true));   // false

儘管有點兒不可思議,但isNaN()確實也適用於對象。在基於對象調用isNaN()函數時,會首先調用對象的valueOf()方法,然後確定該方法返回的值是否可以轉換爲數值。如果不能,則基於這個返回值再調用toString()方法,再測試返回值。


有3個方法可以把非數值轉換爲數值:Number()、parseInt()、parseFloat()

Number()方法轉換規則:

  1. 布爾值:true轉換爲1, false轉換爲0
  2. 數字值:簡單的傳入傳出
  3. undefined:轉換爲NaN
  4. null: 轉換爲0
  5. 字符串:如果只包含數字,則會去掉最前面的0轉換爲十進制;如果字符串包含有效的十六進制數,則轉換爲等值的十進制;空字符串轉換爲0;如包含上述格式以外的字符,轉換爲NaN
  6. 對象:會首先調用對象的valueOf()方法,然後確定該方法返回的值是否可以轉換爲數值。如果不能,則基於這個返回值再調用toString()方法,再測試返回值。

[ 搞懂這個規則再結合NaN的計算規則就可以完全理解任何數值/0的結果 ]

parseInt()計算規則:
這個方法有第二個參數,是指定進制規則的。不傳默認爲十進制。
parseInt()函數在轉換字符串時,更多的是看其是否符合數值模式。它會忽略字符串前面的空格,直至找到第一個非空格字符。如果第一個字符不是數字字符或者負號,parseInt()就會返冋NaN;也就是說,用parseInt()轉換空字符串會返回NaN(Number()對空字符返回0)。如果第一個字符是數字字符,parseInt()會繼續解析第二個字符,直到解析完所有後續字符或者遇到了一個非數字字符。

parseFloat()計算規則:
這個方法只解析十進制。
parseFloat()也是從第一個字符開始解析每個字符。而且也是一直解析到字符串末尾,或者解析到遇見一個無效的浮點數字字符爲止。也就是說,字符串中的第一個小數點是有效的,而第二個小數點就是無效的了,因此它後面的字符申將被忽略。

(6)String

有2個方法可以把非字符串轉換爲字符串:toString()、String()

除了undefined和null都可以使用toString()方法,這個方法接受一個參數,可以指定進制規則。如果可能是undefined或者null,可以用String()方法。

(7)Object

對象其實就是一組數據和功能的集合。對象可以通過執行new操作符後跟要創建的對象類型的名稱來創建。

var o = new Object()

Object的每個實例都具有下列屬性和方法:

  1. Constructor:保存着用於創建當前對象的函數。對於前面的例子而言,構造函數(constructor)就是Object()。
  2. hasOwnProperty(propertyName):用於檢查給定的域性在當前對象實例中(而不是在實例的原型中)是否存在。其中,作爲參數的屬性名(propertyName)必須以字符串形式指定(例如:o.hasOwnProperty ("name") )。
  3. isProtocypeOf(object):用於檢査傳人的對象是否是另一個對象的原型。
  4. propertylsEnumerable(propertyName):用於檢查給定的屬性是否能夠使用for-in語句來枚舉。與hasOwnProperty ()方法一樣,作爲參數的域性名必須以字符串形式指定。
  5. toLocaleString():返回對象的字符串表示,該字符串與執行環境的地區對應。
  6. toString():返回對象的字符串表示。
  7. valueOf():返回對象的字符串、數值或布爾值表示。通常與toString()方法的返回值相同。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章