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這三種類型的賦值是同相似的。函數
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
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是表示無值。
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沒有包裝類
ES6新增的基本類型,只支持函數式賦值,不支持字面量和函數構造。
var sim = Symbol('IBM') // ok sim // Symbol('IBM') typeof sim // 'symbol' sim = new Symbol('IBM') // TypeError: Symbol is not a constructor
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原型繼承