重新回顧一下Javascript中類型相關(guān)的知識
1. 基本類型
Javascript截止目前有7個基本類型:number
, string
, boolean
, undefined
, null
, object
, symbol
1.1 typeof
使用typeof
函數(shù)可以得到對應(yīng)變量/值的基本類型的字符串,但是也存在著一些例外:
typeof 1 === 'number';
typeof '' === 'string';
typeof true === 'boolean';
typeof {} === 'object';
typeof function(){} === 'function'; // function是object的一等公民,并不是基本類型
typeof null === 'object'; //之前說過在javascript中對對象的檢測機制影響導(dǎo)致
typeof undefined === 'undefined';
typeof Symbol() === 'symbol';
我們知道Javascript中存在undefined
和undeclared
兩種情況,undefined
是變量已經(jīng)聲明,但是沒有初始化賦值,此時獲取變量的值為undefined
;而undeclared
是變量并沒有聲明,在詞法作用域中無法找到對應(yīng)的變量,此時獲取變量的值會拋出ReferenceError
。
typeof
對于undeclared
的變量檢測存在一個安全機制,會返回undefined
的字符串,所以當(dāng)我們需要使用一個不能確定是否存在的變量時,我們可以利用typeof
的機制來避免異常的拋出
if(typeof x === 'undefined') { // x如果是undefined或者undecalred會滿足條件
// TODO
}
1.2 值相關(guān)內(nèi)容
不同的基本類型的值存在一些特點:
1.2.1 string
- 對于
string
的值來說,是一個常量,創(chuàng)建以后就不可以發(fā)生改變 -
string
可以從某種程度上可以理解為字符數(shù)組,因此string
在可以使用Array
原型鏈上的方法,但是其本身并不是Array
,所以并不是所有的方法都可以使用(這里存在自動封裝過程)
var s = Array.prototype.join.call('abc', ','); // 可以使用該方法
console.log(s); // a,b,c
var r = Array.prototype.reverse.call('abc'); // 并不能使用該方法,會拋出異常
// 想要實現(xiàn)字符串順序反轉(zhuǎn),可以將字符串轉(zhuǎn)為數(shù)組后利用reverse()函數(shù)后再連接
var r = 'abc'.split('').reverse().join('');
console.log(r); // 'cba'
1.2.2 number
-
number
類型可以分為不帶小數(shù)的數(shù)據(jù)(整數(shù))和帶小數(shù)的數(shù)據(jù),因此對于不帶小數(shù)的數(shù)據(jù)和整數(shù)是一樣的
4.0 === 4
-
number
類型使用的是雙精度的格式,所以在進行計算的時候并不是精確計算,會存在精度的不準確,最常見的例子就是
0.1 + 0.2 != 0.3
這是很讓人費解的結(jié)果,所以在使用含有小數(shù)的數(shù)據(jù)進行計算的時候,最好引入一個誤差精度,兩個數(shù)差值絕對值小于這個值的時候,就認為它們相等,ES6中引入了Number.EPILON
,該值等于Math.pow(2,-52)
。
-
number
類型在較大或者較小的時候,會自動轉(zhuǎn)換為科學(xué)計數(shù)法的方式
5000000000000000000000 // 5e+21
-
number
類型在自動封裝后可以使用toFixed
和toPrecision
分別保留指定小數(shù)位數(shù)和有效數(shù)字位數(shù)(科學(xué)計數(shù)法方式),返回結(jié)果為字符串
0.1234.toFixed(2); // '0.12'
1234.0.toPrecision(2); // '1.2e+3'
但是如果是整數(shù)調(diào)用對應(yīng)方法的時候,要么使用..
的方式,要么手動封裝后調(diào)用,因為自動封裝會默認把第一個.
作為number
自身的值
1234..toPrecision(2); // '1.2e+3'
Number(1234).toPrecision(2); // '1.2e+3'
1.2.3 特殊值
-
void
和任何值進行運算后都只會返回undefined
-
NaN
是特殊的number
,是Javascript中唯一一個不具有自反性的值NaN!==NaN
,因此想要判斷一個變量是不是NaN
可以利用自反性,也可以利用Number
或者Window
中的isNaN
方法
var a = 1 / 'foo';
console.log(a!==a); // true
console.log(isNaN(a)); // true
console.log(Number.isNaN(a)); // true
-
Infinity
是特殊的number
,表示無限的意思,且在兩個無限值進行計算的時候會有以下結(jié)果:
console.log(Infinity + Infinity); // Infinity
console.log(Infinity - Infinity); // NaN
console.log(Infinity * Infinity); // Infinity
console.log(Infinity / Infinity); // NaN
- +0和-0,兩個數(shù)在數(shù)值上并沒有區(qū)別,但是確實可以區(qū)分其意義,如果要進行比較,可以使用
Object.is
函數(shù)進行
console.log(0 === -0); // true
console.log(Object.is(0,-0)); // false
// 也可以使用該函數(shù)對NaN進行比較
console.log(Object.is(NaN, NaN)); // true
1.2.4 值復(fù)制和值引用
只有很簡單的一句話:對于基本類型的值在操作的時候進行值的復(fù)制傳遞,而對于復(fù)合對象在操作的時候進行值的引用傳遞。
2. 內(nèi)置對象
Javascript內(nèi)置對象也是內(nèi)置函數(shù),一共有10個:Number
, String
, Boolean
, Object
, Function
, Array
, RegExp
, Error
, Date
, Symbol
2.1 toString
所有typeof
是object
的對象都有toString
方法,其結(jié)果輸出的對應(yīng)對象的[[Class]]
屬性
Object.prototype.toString.call(Number(1)); // [object Number]
Object.prototype.toString.call(String(''));// [object String]
2.2 自動封裝
基本類型并不存在方法,但是在使用的時候確可以直接使用某些方法,是因為在調(diào)用方法前,Javascript執(zhí)行了自動封裝的過程,所以可以使用對應(yīng)封裝類型的原型方法
2.3 valueOf拆封
對于封裝后的對象(主要是通過顯示的強制類型轉(zhuǎn)換),如果需要得到其基本類型的值,可以使用valueOf
函數(shù)進行拆封
new Boolean(false) === false; // false
new Boolean(false).valueOf() === false; // true
2.4 對象特性
2.4.1 Array
- 創(chuàng)建一個數(shù)組,可以使用字面量的創(chuàng)建方法,也可以使用
Array
構(gòu)造器,其中如果構(gòu)造器傳遞參數(shù)為數(shù)字將創(chuàng)建對應(yīng)長度的空單元數(shù)組
var arr = []; // 字面量創(chuàng)建
var arr = new Array([]); // 構(gòu)造器創(chuàng)建
var arr = Array(3); // new關(guān)鍵字可以省略
console.log(arr.length); // 3;
-
Array
對象的toString
方法調(diào)用將返回通過,
連接的字符串
[1,2,3].toString(); // '1,2,3'
-
Array
對象中,如果存在空單元,那么就稱為稀疏數(shù)組。空單元雖然在某些表現(xiàn)上和undefined
單元相同,但是兩者實際上有所區(qū)別
var arr1 = [undefined, undefined, undefined];
var arr2 = Array(3);
console.log(arr1.length === arr2.length); // true
console.log(arr1[0] === arr2[0]); // true;
// 區(qū)別
Array.prototype.map.call(arr1, (item,i) => { console.log(i);}); // 1 2 3
Array.prototype.map.call(arr2, (item,i) => {console.log(i);}); // [undefined * 3]
- 使用
delete
可以刪除數(shù)組元素,元素刪除后長度不發(fā)生變化,刪除位置變?yōu)榭諉卧?/li>
var a = [1, 2, 3];
delete a[0];
console.log(a);// [undefind * 1, 2, 3];
console.log(a.length); // 3
2.4.2 Date和Error
Date
和Error
沒有字面量的構(gòu)建形式,一定要使用構(gòu)造器的方式去創(chuàng)建對應(yīng)的對象
var date = new Date(); // new關(guān)鍵字不能省略,若只獲取當(dāng)前時間可以使用Date.now()代替
var error = new Error(); // new關(guān)鍵字可以省略
2.4.3 Symbol
ES6引入的新的內(nèi)置對象,通常用來作為對象內(nèi)部私有屬性的key
,構(gòu)建時不能使用new
關(guān)鍵字,且可以使用Object.getOwnPropertySymbols()
獲取當(dāng)前對象所有的symbol
屬性的數(shù)組
var s = Symbol('test');
var obj = {};
obj[s] = 1;
Object.getOwnPropertySymbols(o); // [Symbol(test)]
- 參考
《你不知道的Javscript(中卷)》