閒話JavaScript數據類型

JavaScript支持的類型

JS的內置數據類型羅列以下:segmentfault

undefined
null
bool
number
string
function
object
    Function
        Date
        Error
        自定義function
    new Function
    new Date
    new Error
    new 自定義function
symbol

bool, number, string

bool, number, string這三種類型的賦值是同相似的。函數

字面量方式賦值

var b = true;
var n = 10;
var s = 'hello';

函數式賦值

與字面量方式等價的函數式賦值this

var b = Boolean(true);
var n = Number(10);
var s = String('hello');

可驗證變量的類型:prototype

typeof b; // 'bool'
typeof n; // 'number'
typeof s; // 'string'

基本類型包裝類

假若透過基本類型包裝類構造,那麼這些變量都變成object類型了。code

var obj_b = new Boolean(true);
var obj_n = new Number(10);
var obj_s = new String('hello');

typeof obj_b; // 'object'
typeof obj_n; // 'object'
typeof obj_s; // 'object'

基本類型包裝類實例(obj_b, obj_n, obj_s)可認爲是基本類型字面量(b, n, s),由值類型被封裝成了一個引用類型,兩者之間能夠作比較的。對象

obj_b.valueOf() == b  //true
obj_n.valueOf() == n  //true
obj_s.valueOf() == s  //true

看來基本類型包裝類(Number, Boolean, String)即能當函數直接調用,也能作構造方法,這正是JS函數的魔法。這裏自定義一個函數MyNumber, 模仿Number的實現。繼承

function MyNumber(value) {
    var _self = this;
    // 若是是new構造出來的
    if (_self instanceof MyNumber) {
        _self.value = value;
        return _self;
    }
    return parseFloat(value);
}

MyNumber.prototype.valueOf = function() {
    return parseFloat(this.value);
}

MyNumber.prototype.doubledValue = function() {
    return this.valueOf() * 2;
}

var mnum = MyNumber('12abc');
console.log(mnum);       // 12
console.log(typeof mnum);// number

var obj_mnum = new MyNumber('12abc');
console.log(obj_mnum);  // { [Number: 12] value: '12abc' }
console.log(+obj_mnum); // 12. +用來轉化爲number類型,因此返回.valueOf()的結果
console.log(typeof obj_mnum);        // object
console.log(obj_mnum.doubledValue()) //24

若不用new,也可用Object.create(..prototype),兩者等價。ip

var obj_mnum = Object.create(MyNumber.prototype);
MyNumber.call(obj_mnum, '12abc')

console.log(obj_mnum);  // { [Number: 12] value: '12abc' }
console.log(+obj_mnum); // 12. +用來轉化爲number類型,因此返回.valueOf()的結果
console.log(typeof obj_mnum);        // object
console.log(obj_mnum.doubledValue()) //24

基本類型字面量和基本類型包裝類實例的關係

兩者之間能夠作算數運算:get

obj_n + n //20
// 過程: obj_n是引用類型 
//       ->經過調用其valueOf()轉爲值類型10 
//       -> 10 + 10 = 20

obj_b + obj_n // 11
// 過程:obj_b引用類型
//      -> 調用valueOf()轉爲值類型true
//      -> 布爾true須要轉爲number類型作算數運算,調用Number(true),獲得1
//      obj_n引用類型 -> 轉爲值類型 10
//      因此 1 + 10 = 11

關於JS數據類型轉換詳情,請看Javascript中的類型轉換原型

基本類型何以能調用方法

嚴格來說,基本類型字面量是不能調用任何方法的。可是'hello'.length會成功返回5. 這由於JS解釋器在執行這句代碼時,會生成一個臨時的基本類型包裝類的實例,並調用其length。執行完後,就銷燬了這個臨時變量。

var tmp = new String('hello');
tmp.length

undefined 和 null

變量聲明而不賦值,其值就是undefined

var a;
a === undefined; //true. a 嚴格等於 undefined
typeof a;        // 'undefined'

若賦值爲null:

var a = null;
a === null;      // true
a === undefined; // false, a 再也不嚴格等於undefined
typeof a;        // 'object'

可理解爲,null是有值的,特殊的空值;而undfined是表示無值。

undefined 和 null的一些區別

1.. JSON.stringify會序列化null值,但不會序列化undefined

var obj = {name: 'tom', age: null}
    JSON.stringify(obj) // '{"name":"tom","age":null}'
    
    var obj = {name: 'tom', age: undefined} //'{"name":"tom"}'
對象實例的字段聲明爲undefined,是無心義的。

2.. undefined會觸發ES6的default value,而null不會。

function greet(name='world') {
        console.log('hello', name)
    }
    greet()          //hello world
    greet(undefined) //hello world
    greet(null)      //hello null

這裏也進一步印證了, null自己是有值的,不過是個特殊的空值。而undefined是無值的。

值得一提的是,基本類型undefined/null是沒有任何方法的,也不可以調用其任何方法。這根bool/number/string不一樣,這由於是undefined/null沒有包裝類

symbol

ES6新增的基本類型,只支持函數式賦值,不支持字面量和函數構造。

var sim = Symbol('IBM') // ok
sim                     // Symbol('IBM')
typeof sim              // 'symbol'
sim = new Symbol('IBM') // TypeError: Symbol is not a constructor

function 和 Function

JS函數能夠經過new Function構造,但一般用function關鍵字定義。兩者的關聯,已在獨家解析Javascript原型繼承 - 之函數原型和AOP有詳細的闡述。這裏就簡要說明下,函數自己和函數構造實例的一點區別。

type of Date // function. Date自己是函數
typeof new Date() // object. 經過new Date構造出來的是object實例
new Date().__proto__ == Date.prototype //true. 
// new Date()既然是由Date函數構造出來的,
// 因此new Date()的run-time  __proto__就是Date的design-time的prototype

// new Date()就是Date的構造實例了
new Date() instanceof Date // true.

關於 run-time __proto__和design-time prototype,請讀者參考獨家解析Javascript原型繼承

相關文章
相關標籤/搜索