最全Javascript數據類型解析

數據類型

最新的 ECMAScript 標準定義了 7 種數據類型:javascript

  1. 6種原型數據類型(primitive type):
  • undefined. 變量未定義時的屬性。
  • null. 一個代表 null 值的特殊關鍵字。 JavaScript 是大小寫敏感的,所以 null 與 Null、NULL或其餘變量徹底不一樣。
  • Boolean. 布爾值,true 和 false.
  • Number. 表示數字,例如: 42 或者 3.14159。
  • String. 表示字符串,例如:"Howdy"
  • Symbol ( 在 ECMAScript 6 中新添加的類型).。一種數據類型,它的實例是惟一且不可改變的。
  1. 以及 Object 對象。(complex type 複雜類型)

undefined 類型

Undefined類型只有一個值undefined,表示"缺乏值",就是此處應該有一個值,可是尚未定義。主要的用法:html

(1)變量被聲明瞭,但沒有賦值時,就等於undefined。
(2) 調用函數時,應該提供的參數沒有提供,該參數等於undefined。
(3)對象沒有賦值的屬性,該屬性的值爲undefined。
(4)函數沒有返回值時,默認返回undefined。
PS: 值 undefined 並不一樣於未定義的值。可是,typeof 運算符並不真正區分這兩種值。
var i;
console.log(i) ; // undefined

function f(x){console.log(x)}
f();  // undefined

var  o = new Object();
console.log(o.p);  // undefined

var func = f();
console.log(func);  // undefined

console.log(typeof y); //"undefined"

null 類型

null類型的默認值是null,從邏輯角度講,是表示一個空對象指針,表示"沒有對象",即該處不該該有值。主要用法:java

(1) 做爲函數的參數,表示該函數的參數不是對象。
(2) 做爲對象原型鏈的終點。
Object.getPrototypeOf(Object.prototype)  // null

區別undefined:git

當一個變量聲明後,未初始化,則該值爲undefined,若是這個值是爲了保存對象,則修改其默認初始化的值,改成null。 因此當檢測其類型時,會顯示類型爲object。
typeof null        // object (歷史緣由,不是'null')
typeof undefined   // "undefined"
null === undefined // false
null  == undefined // true
null === null // true
null == null // true
!null // true
Number(null) // 0
Number(undefined) // NaN
isNaN(1 + null) // false
isNaN(1 + undefined) // true

Boolean 類型

布爾類型,該類型有兩個值:true false。Bloolean()函數,能夠將其餘類型的值轉換爲布爾類型。同時也存在隱式類型轉換。es6

這裏區分一下Truthy類型和Falsy類型值。
Falsy類型值包括: "", 0, null, undefined, NaN, false
除了Falsy類型值之外的都被稱爲Truthy類型值,它們會被轉換爲 true
Boolean(null)         // false
Boolean('hello')      // true 
Boolean('0')          // true 
Boolean(' ')          // true 
Boolean([])           // true 
Boolean(function(){}) // true

Number 類型

根據 ECMAScript 標準,JavaScript 中只有一種數字類型:基於 IEEE 754 標準的雙精度 64 位二進制格式的值(-(263 -1) 到 263 -1)。它並無爲整數給出一種特定的類型。除了可以表示浮點數外,還有一些帶符號的值:+Infinity,-Infinity 和 NaN (非數值,Not-a-Number)。
整數能夠用十進制(基數爲10)、十六進制(基數爲16)、八進制(基數爲8)以及二進制(基數爲2)的字面值來表示。json

0, 117 and -345 (十進制, 基數爲10)
015, 0001 and -0o77 (八進制, 基數爲8) 
0x1123, 0x00111 and -0xF1A7 (十六進制, 基數爲16或"hex")
0b11, 0b0011 and -0b11 (二進制, 基數爲2)

浮點數(有趣的一點是,在計算前其存儲爲字符串)所佔據的內存空間是整數的兩倍。
語法:[(+|-)][digits][.digits][(E|e)[(+|-)]digits]segmentfault

3.14      
-.2345789 // -0.23456789
-3.12e+12  // -3.12*1012
.1e-23    // 0.1*10-23=10-24=1e-24

NaN:
一、即非數值,是一個特殊的值,這個數值用於表示一個原本要返回數值的操做數,未返回數值的狀況。好比任何數值除以0,本是不符合規範的,js裏,這樣的操做返回NaN(可是實際上,只有0除以0時返回NaN,其餘則無窮值)。數組

二、NaN有兩個不一樣尋常的特色:任何涉及NaN的操做都會返回NaNNaN值與任何值都不相等,包括自己。
三、isNaN()函數,這個函數能夠判斷,傳遞的參數是否「不是數值」這裏涉及數值轉換的問題,例如「10」這個字符串就能夠轉換爲10,可是「blue」這個字符串則沒法轉換爲數字,因此isNaN("blue")==true 安全

+0 === -0  //true
42 / +0; // Infinity
42 / -0; // -Infinity
NaN == NaN //false

+Infinity,-Infinity:
要檢查值是否大於或小於 +/-Infinity,你可使用常量 Number.MAX_VALUENumber.MIN_VALUE。另外在 ECMAScript 6 中,你也能夠經過 Number.isSafeInteger() 方法還有 Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER 來檢查值是否在雙精度浮點數的取值範圍內。 超出這個範圍,JavaScript 中的數字再也不安全了,也就是隻有 second mathematical interger 能夠在 JavaScript 數字類型中正確表現。app

String 類型

這個算是比較熟悉的了這裏引用一下MDN的描述。
JavaScript的字符串類型用於表示文本數據。它是一組16位的無符號整數值的「元素」。在字符串中的每一個元素佔據了字符串的位置。第一個元素的索引爲0,下一個是索引1,依此類推。字符串的長度是它的元素的數量。
不一樣於類 C 語言,JavaScript 字符串是不可更改的。這意味着字符串一旦被建立,就不能被修改。可是,能夠基於對原始字符串的操做來建立新的字符串。
主要強調一下ES2015的模板字符串:

// Basic literal string creation
`In JavaScript '\n' is a line-feed.`

// Multiline strings
`In JavaScript this is
 not legal.`

// String interpolation
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

// Construct an HTTP request prefix is used to interpret the replacements and construction
POST`http://foo.org/bar?a=${a}&b=${b}
     Content-Type: application/json
     X-Credentials: ${credentials}
     { "foo": ${foo},
       "bar": ${bar}}`(myOnReadyStateChangeHandler);
String()函數能夠將任何類型的值轉換爲字符串,包括 null轉換爲 'null'undefined轉換爲 'undefined'

Symbol 類型

語法:Symbol([description])
一、每一個從Symbol()返回的symbol值都是惟一的。
直接使用Symbol()建立新的symbol類型,並用一個字符串(可省略)做爲其描述。如下代碼建立了三個新的symbol類型。 字符串 「foo」 的做用僅爲描述,它每次都會建立一個新的 symbol類型:

var sym1 = Symbol();
var sym2 = Symbol('foo');
var sym3 = Symbol('foo');
Symbol("foo") === Symbol("foo"); // false

還可使用Symbol.for方法建立新的symbol類型,和前者區別Symbol.for()會把symbol值以一個key值登記到全局環境中,Symbol()就不會。Symbol.for()不會每次調用就返回一個新的 Symbol 類型的值,而是會先檢查給定的key是否已經存在,若是不存在纔會新建一個值。好比,若是你調用Symbol.for("cat")30 次,每次都會返回同一個 Symbol 值,可是調用Symbol("cat")30 次,會返回 30 個不一樣的 Symbol 值。查看登記的Symbol值可使用Symbol.keyFor方法,該方法返回一個已登記的 Symbol 類型值的key。

let sym1 = Symbol('foo');
let sym2 = Symbol('foo');
let sym3 = Symbol.for('foo');
let sym4 = Symbol.for('foo');
sym1 === sym2  //false
sym3 === sym4  //true
Symbol.keyFor(sym1) //undefined
Symbol.keyFor(sym3) //"foo"

二、 再也不支持new 運算符的語法:

var sym = new Symbol(); // TypeError

這會阻止建立一個顯式的 Symbol 包裝器對象而不是一個 Symbol 值。圍繞原始數據類型建立一個顯式包裝器對象從 ECMAScript 6 開始再也不被支持。 然而,現有的原始包裝器對象,如 new Boolean、new String以及new Number由於遺留緣由仍可被建立。

三、特殊的類型轉換
Symbol 值不能與其餘類型的值進行運算。
Symbol 值能夠顯式轉爲字符串、布爾值,可是不能轉爲數值。

四、用於對象屬性名(主要)
Symbol 值做爲對象屬性名時,不能用點運算符。通常經過方括號結構和Object.defineProperty,將對象的屬性名指定爲一個 Symbol 值。

let sym1 = Symbol();
let sym2 = Symbol();
let sym3 = Symbol();

let a = {
  [sym1]: 'Symbol1';
};
a[sym2] = 'Symbol2';
Object.defineProperty(a, sym3, { value: 'Symbol3' });

a.sym1 = 'Hello!';
a[sym1] // "Symbol1"
a['sym1'] // "Hello!"

Symbol 做爲屬性名,該屬性不會出如今for...infor...of循環中,也不會被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回。可是,它也不是私有屬性,有一個Object.getOwnPropertySymbols方法,返回一個數組,成員是當前對象的全部用做屬性名的 Symbol 值。

更多的Symbol相關內容參考這篇文章—— 傳送門

對象

在計算機科學中, 對象是指內存中的能夠被標識符引用的一塊區域。
對象屬於複雜數據類型,也能夠說是引用類型(邏輯上等價於class/類)。相對於原始數據類型的直接存取(棧內存),複雜數據類型的存儲方式爲引用(堆內存,棧內存保存對應的指針)。

Object 對象

ECMAScript 中的全部對象都由這個對象繼承而來,Object 對象中的全部屬性和方法都會出如今其餘對象中,因此理解了 Object 對象,就能夠更好地理解其餘對象。
本文主要介紹如下幾點:

  • Object()做爲函數以及Object()構造函數
  • Object靜態方法
  • Object實例方法

一、Object()與new Object()
Object函數能夠把任意值轉換爲對象;new Object()則是生成新對象,能夠簡寫爲{}。除語義上的不一樣外,二者的用法相同,如下以Object()爲例:

var obj = Object();
var obj = Object(undefined);
var obj = Object(null);
//以上語句等效,返回空對象
obj instanceof Object // true

var obj = Object(1);
obj instanceof Object // true
obj instanceof Number // true

var obj = Object('foo');
obj instanceof Object // true
obj instanceof String // true

var obj = Object(true);
obj instanceof Object // true
obj instanceof Boolean // true

若是參數原本就是一個對象便不須要轉換,直接返回該對象:

var arr = [];
var obj = Object(arr); // 返回原數組
obj === arr // true

var value = {};
var obj = Object(value) // 返回原對象
obj === value // true

var fn = function () {};
var obj = Object(fn); // 返回原函數
obj === fn // true

二、Object靜態方法
所謂「靜態方法」,是指部署在Object對象自身的方法。例如:Object.key = value{key:value}
通常使用Object.keys方法和Object.getOwnPropertyNames方法來遍歷對象的屬性。區別在於後者能夠列舉不可枚舉的屬性名,例如數組的length

var a = ['Hello', 'World'];

Object.keys(a) // ["0", "1"]
Object.getOwnPropertyNames(a) // ["0", "1", "length"]

其餘靜態方法:(傳送門)
1)對象屬性模型的相關方法

  • Object.getOwnPropertyDescriptor():獲取某個屬性的描述對象。
  • Object.defineProperty():經過描述對象,定義某個屬性。定義key爲Symbol的屬性的方法之一。
  • Object.defineProperties():經過描述對象,定義多個屬性。

2)控制對象狀態的方法

  • Object.preventExtensions():防止對象擴展。
  • Object.isExtensible():判斷對象是否可擴展。
  • Object.seal():禁止對象配置。
  • Object.isSealed():判斷一個對象是否可配置。
  • Object.freeze():凍結一個對象。
  • Object.isFrozen():判斷一個對象是否被凍結。

3)原型鏈相關方法

  • Object.assign(target, ...sources):用於將全部可枚舉屬性的值從一個或多個源對象複製到目標對象。它將返回目標對象。
  • Object.create():該方法能夠指定原型對象和屬性,返回一個新的對象。
  • Object.getPrototypeOf():獲取對象的Prototype對象。

三、Object實例方法
定義在Object.prototype的·對象稱爲實例方法,全部Object的實例對象都繼承了這些方法。
Object實例對象的方法,主要有如下六個。

  • Object.prototype.valueOf():返回當前對象對應的值。
  • Object.prototype.toString():返回當前對象對應的字符串形式。檢測對象類型。
  • Object.prototype.toLocaleString():返回當前對象對應的本地字符串形式。
  • Object.prototype.hasOwnProperty():判斷某個屬性是否爲當前對象自身的屬性,仍是繼承自原型對象的屬性。
  • Object.prototype.isPrototypeOf():判斷當前對象是否爲另外一個對象的原型。
  • Object.prototype.propertyIsEnumerable():判斷某個屬性是否可枚舉。

數據類型判斷

之因此會說到這個判斷問題,主要緣由是typeof是不太靠譜的。首先JavaScript是動態數據類型的語言,不少類型檢查是沒必要要的。在具體實現上的問題,在實際的項目應用中,typeof也只有兩個用途,就是檢測一個元素是否爲undefined,或者是否爲function。由下面的表格可見一斑:

Value               function   typeof
-------------------------------------
"foo"               String     string
new String("foo")   String     object
1.2                 Number     number
new Number(1.2)     Number     object
true                Boolean    boolean
new Boolean(true)   Boolean    object
new Date()          Date       object
new Error()         Error      object
[1,2,3]             Array      object
new Array(1, 2, 3)  Array      object
new Function("")    Function   function
/abc/g              RegExp     object
new RegExp("meow")  RegExp     object
{}                  Object     object
new Object()        Object     object

若是仍是要判斷的話,公認的靠譜解法是 Object.prototype.toString.call(x) === '[object type]'。具體實現能夠參考jQuery.type()源碼。另外經過構造函數建立的對象均可以用 instanceof 檢查。

參考

  1. http://www.ruanyifeng.com/blo...
  2. https://zhuanlan.zhihu.com/p/...
  3. https://developer.mozilla.org...
  4. https://developer.mozilla.org...
  5. https://javascript.ruanyifeng...
  6. https://segmentfault.com/q/10...
相關文章
相關標籤/搜索