深入探討javascript中的數(shù)據(jù)類型
學(xué)一門編程語言,無非兩方面:一是語法,二是數(shù)據(jù)類型。類C語言的語法不外乎if、while、for、函數(shù)、算術(shù)運算等,面向?qū)ο蟮恼Z言再加上object。
語法只是語言設(shè)計者預(yù)先做的一套規(guī)則,不同語言語法不盡相同,但都有一些共通點,對于熟悉一兩門編程語言的人,學(xué)其他的編程語言時,語法往往不是問題(當(dāng)然,如果你一直學(xué)的是類C語言,那么首次接觸lisp時肯定也要花些時間),學(xué)習(xí)的重點往往是數(shù)據(jù)類型及其相關(guān)操作上,不是有句老話:“數(shù)據(jù)結(jié)構(gòu)+算法=程序”!其次,有些語言的語法本身就存在設(shè)計問題(javascript更甚),我們沒必要深究這些點,當(dāng)然,如果你自詡geek,可以把玩把玩。
本文將對javascript中的數(shù)據(jù)類型做一個詳盡的介紹。
弱類型 vs 強類型
鑒于javascript的設(shè)計理念,javascript被設(shè)計成一種弱類型的語言。
說到這里,難免要說一下,弱類型與強類型的區(qū)別。
一些人會誤以為這兩者的差別就是“強類型的語言在聲明一個變量時需要指明它的類型,而弱類型的則不用”。其實這種觀點是錯誤的。比如下面這個Java代碼片段:
String s = "hello";
int l = s.getBytes().length;
編譯器是怎么知道.length是合法的表達(dá)式呢?這是因為編譯器知道s的數(shù)據(jù)類型為String,當(dāng)調(diào)用String的getBytes方法時,返回值的數(shù)據(jù)類型為byte[],所以.length是合法的表達(dá)式。
這兩者真正的區(qū)別是:
在強類型的語言,每個表達(dá)式的類型都能夠在編譯時確定,并且只允許適用于該類型的操作;
弱類型的語言允許對任意類型施加任何操作,只是這個操作有可能在運行時報錯。
數(shù)據(jù)類型
根據(jù)ECMAScript 5.1的規(guī)范,javascript中共有六種數(shù)據(jù)類型,分別為:Undefined, Null, Boolean, Number, String、Object。前五種屬于基本類型,最后一種屬于對象類型。
基本數(shù)據(jù)類型
Undefined類型只有一個值,為undefined,意味著“空值(no value)”,適用于所有數(shù)據(jù)類型。
Null類型只有一個值,為null,意味著“空對象(no object)”,只適用于對象類型。
Boolean類型有兩個值,為true與false
Number類型的值是遵循IEEE 754標(biāo)準(zhǔn)的64位浮點數(shù)的集合,類似于Java的double。沒有整型數(shù)據(jù)結(jié)構(gòu)。此外還包含三個特殊的值:NaN、Infinity、-Infinity
String類型的值是有窮個Unicode字符的集合。必須用'或"括起來。
null與undefined
null與undefined都表示“沒有值(non-value)”的概念,如果嚴(yán)格區(qū)分:
- null表示空
- undefined表示不存在。沒有初始化的變量、函數(shù)中缺失的參數(shù)、函數(shù)沒有顯式return值時都為此值
在其他語言中,一般只用一個null來表示空值,javascript中為什么多了個undefined呢?這是歷史原因造成的:
javascript采用了Java的語法,把類型分為了基本類型與對象類型,Java中用null來表示空對象,javascript想當(dāng)然的繼承了過來;在C語言中,null在轉(zhuǎn)為數(shù)字時為0,javascript也采取同樣的方式:
> Number(null)
0
> 5 + null
5
在javascript1.0時,還沒有異常處理(exception handling),對于一些異常情況(沒有初始化的變量、調(diào)用函數(shù)時缺失的參數(shù)等),需要標(biāo)明為一種特殊的值,null本來是個很好的選擇,但是Brendan Eich同時想避免下面兩件事:
- 這個特殊值不應(yīng)該有引用的特性,因為那是對象特有的
- 這個特殊值不應(yīng)該能轉(zhuǎn)為0,因為這樣不容易發(fā)現(xiàn)程序中的錯誤
基于這兩個原因,Brendan Eich選擇了undefined,它可以被強轉(zhuǎn)為NaN。
> Number(undefined)
NaN
> 5 + undefined
NaN
兩者在于JSON對象打交道時,結(jié)果也迥然不同:
> JSON.parse(null)
null
> JSON.parse(undefined)
//Firfox SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
//Chrome SyntaxError: Unexpected token u
> JSON.stringify(null)
"null"
> JSON.stringify(undefined)
undefined
對象類型
javascript作為一門腳本語言,本身功能十分精簡,很多功能(文件讀寫、網(wǎng)絡(luò)等)都是由宿主環(huán)境提供。宿主環(huán)境與javascript語言的橋梁是對象,宿主環(huán)境通過提供一系列符合javascript語法的對象,提供各種各樣的功能。
在javascript面向?qū)ο缶幊踢@篇文章(如果你不知道prototype是什么,強烈建議看看這篇文章)里,我多次強調(diào)了對象在javascript中就是一系列的鍵值對,就像Java中的HashMap一樣,不過,javascript中對象的屬性可以有一些描述符(property descriptor),這在HashMap中是沒有的。
屬性描述符
屬性描述符分為兩類:
數(shù)據(jù)描述符(data descriptor),包含一系列boolean值,用以說明該屬性是否允許修改、刪除。
訪問描述符(accessor descriptor),包含get與set函數(shù)。
這兩種描述符都是對象,它們都擁有下面兩個boolean屬性:
configurable 用以指定該描述符是否允許修改、刪除。默認(rèn)為false。
enumerable 用以指定在遍歷對象(使用for...in循環(huán)或Object.keys方法)的屬性時,是否訪問該屬性。默認(rèn)為false。
除了上面這兩個共有屬性外,數(shù)據(jù)描述符還有下面兩個屬性:
- value 用以指定該屬性的值,默認(rèn)為undefined
- writable 用以指定該屬性的值是否允許改變該屬性的值,默認(rèn)為false
訪問描述符還有下面兩個屬性:
- get 用以指定訪問該屬性時的訪問器(getter,本質(zhì)是個函數(shù)),該訪問器的返回值為該屬性的值。默認(rèn)為undefined
- set 用以指定訪問該屬性時的賦值器(setter,本質(zhì)是個函數(shù)),該賦值器的接受一個參數(shù)。默認(rèn)為undefined
我們可以使用Object.defineProperty來設(shè)置對象的屬性描述符。例如:
// using __proto__
Object.defineProperty(obj, 'key', {
__proto__: null, // no inherited properties
value: 'static' // not enumerable
// not configurable
// not writable
// as defaults
});
通過上面這個例子可以看出,描述符具有繼承的特點,我們這里顯式的把描述符對象的__proto__設(shè)為null,就避免了從Object.prototype中繼承相應(yīng)屬性。當(dāng)然我們也可以顯式地設(shè)置描述符的所有屬性:
// being explicit
Object.defineProperty(obj, 'key', {
enumerable: false,
configurable: false,
writable: false,
value: 'static'
});
這樣的效果和第一段代碼的效果是一樣的。
下面再舉一個訪問描述符的例子:
// Example of an object property added with defineProperty with an accessor property descriptor
var bValue = 38;
Object.defineProperty(obj, 'key', {
get: function() { return bValue; },
set: function(newValue) { bValue = newValue; },
enumerable: true,
configurable: true
});
需要注意的是,不能混淆了訪問描述器與數(shù)據(jù)描述器。下面這樣寫是錯誤的:
// You cannot try to mix both:
Object.defineProperty(obj, 'conflict', {
value: 0x9f91102,
get: function() { return 0xdeadbeef; }
});
// throws a TypeError: property descriptors must not specify a value
// or be writable when a getter or setter has been specified
typeof
如果想在運行時獲知某變量的類型,可以使用typeof操作符。typeof的返回值如下表:
其中有一處需要注意,那就是typeof null == "object",按照ECMAScript 5.1標(biāo)準(zhǔn),Null類型應(yīng)該是個基本類型,為什么這里返回object呢?原因是這樣的:
在javascript 1.0中,javascript中的值是用一個類型標(biāo)志(type tag)和一個實際值這樣的結(jié)構(gòu)表示的,對象的類型標(biāo)志為0,null在C語言中表示NULL指針(0x00),所以null的類型標(biāo)志就為0了。
以上就是本文的全部內(nèi)容了,有需要的小伙伴參考下吧。
相關(guān)文章
Javascript基礎(chǔ) 函數(shù)“重載” 詳細(xì)介紹
這篇文章介紹了Javascript基礎(chǔ) 函數(shù)“重載” ,有需要的朋友可以參考一下2013-10-10Javascript & DHTML 實例編程(教程)基礎(chǔ)知識
Javascript & DHTML 實例編程(教程)基礎(chǔ)知識...2007-06-06JavaScript獲取tr td 的三種方式全面總結(jié)(推薦)
這篇文章主要介紹了JavaScript獲取tr td 的三種方式,具體操作步驟大家可查看下文詳細(xì)講解,感興趣的小伙伴們可以參考一下。2017-08-08javascript 學(xué)習(xí)筆記(八)javascript對象
昨天看了些有關(guān)javascript對象方面的文章,以下是自己的一些學(xué)習(xí)心得及體會,希望同大家共同討論!2011-04-04Javascript的時間戳和php的時間戳轉(zhuǎn)換注意事項
需要注意的是js的時間戳是13位,php的時間戳是10位,轉(zhuǎn)換函數(shù)如下,感興趣的朋友可以參考下哈2013-04-04