一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

JavaScript中的類型

一、關(guān)于類型

什么叫做類型?簡(jiǎn)單地說(shuō),類型就是把內(nèi)存中的一個(gè)二進(jìn)制序列賦予某種意義。比如,二進(jìn)制序列0100 0000 0111 0000 0001 0101 0100 1011 1100 0110 1010 0111 1110 1111 1001 1110如果看作是64位無(wú)符號(hào)整數(shù)類型就是4643234631018606494 而按照IEEE 754規(guī)定的浮點(diǎn)數(shù)二進(jìn)制表示規(guī)則(見(jiàn)附1)雙精度浮點(diǎn)類型則是257.331。

變量類型

大部分計(jì)算機(jī)語(yǔ)言使用變量來(lái)存儲(chǔ)和表示數(shù)據(jù),一些語(yǔ)言會(huì)給變量規(guī)定一個(gè)類型,在整個(gè)程序中(不論是編譯時(shí)還是運(yùn)行時(shí)),這個(gè)類型都不能被改變。與此相對(duì),JavaScript和一些其它語(yǔ)言的變量可以存儲(chǔ)任何類型,它們使用無(wú)類型的變量。變量類型是否存在,是跟語(yǔ)法無(wú)關(guān)的,例如C#中也提供了var類型的變量,但是,下面的語(yǔ)句在C#中會(huì)出錯(cuò):

var a=1;

a=”string”;

原因是C#的var關(guān)鍵字只是省略了變量類型聲明,而根據(jù)初始化表達(dá)式自動(dòng)推斷變量類型,所以C#的var變量仍然是有類型的。而JavaScript中,任何時(shí)刻你都可以把任何值賦值給特定變量,所以JavaScript變量是無(wú)類型的。

強(qiáng)類型和弱類型

按照計(jì)算機(jī)語(yǔ)言的類型系統(tǒng)的設(shè)計(jì)方式,可以分為強(qiáng)類型和弱類型兩種。二者之間的區(qū)別,就在于計(jì)算時(shí)是否可以不同類型之間對(duì)使用者透明地隱式轉(zhuǎn)換。從使用者的角度來(lái)看,如果一個(gè)語(yǔ)言可以隱式轉(zhuǎn)換它的所有類型,那么它的變量、表達(dá)式等在參與運(yùn)算時(shí),即使類型不正確,也能通過(guò)隱式轉(zhuǎn)換來(lái)得到正確地類型,這對(duì)使用者而言,就好像所有類型都能進(jìn)行所有運(yùn)算一樣,所以這樣的語(yǔ)言被稱作弱類型。與此相對(duì),強(qiáng)類型語(yǔ)言的類型之間不一定有隱式轉(zhuǎn)換(比如C++是一門強(qiáng)類型語(yǔ)言,但C++中double和int可以互相轉(zhuǎn)換,但double和任何類型的指針之間都需要強(qiáng)制轉(zhuǎn)換)

為什么要有類型

類型可以幫助程序員編寫正確的程序,它在實(shí)際編寫程序的過(guò)程中體現(xiàn)為一種約束。一般規(guī)律是,約束越強(qiáng)越不容易出錯(cuò),但編寫程序時(shí)也越麻煩。變量有類型的強(qiáng)類型語(yǔ)言約束最強(qiáng),典型代表是C++,變量無(wú)類型的弱類型語(yǔ)言約束最弱,典型代表是JavaScript。在JavaScript中,因?yàn)榧s束比較弱,所以容易出現(xiàn)這種錯(cuò)誤:

var a =200;

var b ="1";

var c= a + b;

你可能期望c是201,但實(shí)際上它是"2001",這個(gè)錯(cuò)誤在強(qiáng)類型語(yǔ)言中決不會(huì)出現(xiàn)。然而正是因?yàn)?a href=/itjie/Javajishu/ target=_blank class=infotextkey>JavaScript沒(méi)有這些約束,所以可以很方便地拼接數(shù)字和字符串類型。所以,約束和靈活性對(duì)語(yǔ)言的設(shè)計(jì)者而言,永遠(yuǎn)是需要平衡的一組特性。

靜態(tài)類型和動(dòng)態(tài)類型

類型是一種約束,這種約束是通過(guò)類型檢查來(lái)發(fā)生作用的。在不同語(yǔ)言中,類型檢查在不同的階段發(fā)生作用,這樣又可以分為編譯時(shí)檢查和運(yùn)行時(shí)檢查。對(duì)于JavaScript這樣的解釋型語(yǔ)言,也有跟編譯過(guò)程比較相似的階段,即詞法分析和語(yǔ)法分析,解釋型語(yǔ)言的類型檢查若在語(yǔ)法分析或者之前的階段完成,也可以認(rèn)為類似于編譯時(shí)檢查。所以更合理的說(shuō)法是靜態(tài)類型檢查和動(dòng)態(tài)類型檢查。

有趣的是,很多語(yǔ)言雖然編譯時(shí)檢查類型,但是它的類型信息仍可以在運(yùn)行時(shí)獲得,如C#中使用元數(shù)據(jù)來(lái)保存類型信息,在運(yùn)行階段,使用者可以通過(guò)反射來(lái)獲取和使用類型的信息。

JavaScript在設(shè)計(jì)的各個(gè)方面都以靈活性優(yōu)先,所以它使用動(dòng)態(tài)類型檢查,并且除了在進(jìn)行極少數(shù)特定操作時(shí),JavaScript不會(huì)主動(dòng)檢查類型。你可以在運(yùn)行時(shí)獲得任何一個(gè)變量或者表達(dá)式的類型信息并且通過(guò)程序邏輯檢查它的正確性。

二、JavaScript標(biāo)準(zhǔn)規(guī)定的類型

JavaScript標(biāo)準(zhǔn)中規(guī)定了9種類型:Undefined Null Boolean String Number Object Reference List Completion

其中,Reference List Completion三種類型僅供語(yǔ)言解析運(yùn)行時(shí)使用,無(wú)法從程序中直接訪問(wèn),這里就暫不做介紹。下面我們可以了解下這六種類型:

Undefined類型

Undefined類型只有一個(gè)值undefined,它是變量未被賦值時(shí)的值,在JS中全局對(duì)象有一個(gè)undefined屬性表示undefined,事實(shí)上undefined并非JavaScript的關(guān)鍵字,可以給全局的undefined屬性賦值來(lái)改變它的值。

Null類型

Null類型也只有一個(gè)值null,但是JavaScript為它提供了一個(gè)關(guān)鍵字null來(lái)表示這個(gè)唯一的值。Null類型的語(yǔ)義是“一個(gè)空的對(duì)象引用”。

Boolean類型

Boolean有兩種取值true和false

String類型

String類型的的正式解釋是一個(gè)16位無(wú)符號(hào)整數(shù)類型的序列,它實(shí)際上用來(lái)表示以UTF-16編碼的文本信息。

Number類型

JavaScript的Number共有18437736874454810627 (就是 264-253 +3)個(gè)值。JavaScript的Number以雙精度浮點(diǎn)類型存儲(chǔ),除了9007199254740990表示NaN,它遵守IEEE 754(見(jiàn)附1)規(guī)定,占用64位8字節(jié)。

Object類型

JavaScript中最為復(fù)雜的類型就是Object,它是一系列屬性的無(wú)序集合,F(xiàn)unction是實(shí)現(xiàn)了私有屬性[[call]]的Object,JavaScript的宿主也可以提供一些特別的對(duì)象。

三、JavaScript使用者眼中的類型:

前面講了JS標(biāo)準(zhǔn)中規(guī)定的類型,然而一個(gè)不能忽略的問(wèn)題是JS標(biāo)準(zhǔn)是寫給JS實(shí)現(xiàn)者看的,對(duì)JS使用者而言,類型并不一定要按照標(biāo)準(zhǔn)來(lái)定義,比如,因?yàn)镴S在進(jìn)行.運(yùn)算的時(shí)候,會(huì)自動(dòng)把非Object類型轉(zhuǎn)換為與其對(duì)應(yīng)的對(duì)象,所以"str".length其實(shí)和(new String("str")).length是等效的,從這個(gè)角度而言,認(rèn)為二者屬于同一類型也未嘗不可。我們利用JS中的一些語(yǔ)言特性,可以進(jìn)行運(yùn)行時(shí)的類型判別,但是這些方法判斷的結(jié)果各不相同,孰好孰壞還需要您自己決定。

typeof——看上去很官方

typeof是JS語(yǔ)言中的一個(gè)運(yùn)算符,從它的字面來(lái)看,顯然它是用來(lái)獲取類型的,按JavaScript標(biāo)準(zhǔn)的規(guī)定,typeof獲取變量類型名稱的字符串表示,他可能得到的結(jié)果有6種:string、bool、number、undefined、object、function,而且JavaScript標(biāo)準(zhǔn)允許其實(shí)現(xiàn)者自定義一些對(duì)象的typeof值。

在JS標(biāo)準(zhǔn)中有這樣一個(gè)描述列表:

Type

Result

Undefined

"undefined"

Null

"object"

Boolean

"boolean"

Number

"number"

String

"string"

Object (native and doesn't implement [[call]])

"object"

Object (native and implements [[call]])

"function"

Object (host)

Implementation-dependent

下面一個(gè)例子來(lái)自51js的Rimifon,它展示了IE中typeof的結(jié)果產(chǎn)生"date"和"unknown"的情況:

var xml=document.createElement("xml");
var rs=xml.recordset;
rs.Fields.Append("date", 7, 1);
rs.Fields.Append("bin", 205, 1);
rs.Open();
rs.AddNew();
rs.Fields.Item("date").Value = 0;
rs.Fields.Item("bin").Value = 21704;
rs.Update();
var date = rs.Fields.Item("date").Value;
var bin = rs.Fields.Item("bin").Value;
rs.Close();
alert(date);
alert(bin);
alert([typeof date, typeof bin]);
try{alert(date.getDate())}catch(err){alert(err.message)}

關(guān)于這個(gè)最為接近"類型"語(yǔ)義的判斷方式,實(shí)際上有不少的批評(píng),其中之一是它無(wú)法分辨不同的object,new String("abc")和new Number(123)使用typeof無(wú)法區(qū)分,由于JS編程中,往往會(huì)大量使用各種對(duì)象,而typeof對(duì)所有對(duì)象都只能給出一個(gè)模糊的結(jié)果"object",這使得它的實(shí)用性大大降低。

instanceof——原型還是類型?

instanceof的意思翻譯成中文就是"是……的實(shí)例",從字面意思理解它是一個(gè)基于類面向?qū)ο缶幊痰男g(shù)語(yǔ),而JS實(shí)際上沒(méi)有在語(yǔ)言級(jí)別對(duì)基于類的編程提供支持。JavaScript標(biāo)準(zhǔn)雖然只字未提,但其實(shí)一些內(nèi)置對(duì)象的設(shè)計(jì)和運(yùn)算符設(shè)置都暗示了一個(gè)"官方的"實(shí)現(xiàn)類的方式,即從把函數(shù)當(dāng)作類使用,new運(yùn)算符作用于函數(shù)時(shí),將函數(shù)的prototype屬性設(shè)置為新構(gòu)造對(duì)象的原型,并且將函數(shù)本身作為構(gòu)造函數(shù)。

所以從同一個(gè)函數(shù)的new運(yùn)算構(gòu)造出的對(duì)象,被認(rèn)為是一個(gè)類的實(shí)例,這些對(duì)象的共同點(diǎn)是:1.有同一個(gè)原型 2.經(jīng)過(guò)同一個(gè)構(gòu)造函數(shù)處理。而instanceof正是配合這種實(shí)現(xiàn)類的方式檢查"實(shí)例是否屬于一個(gè)類"的一種運(yùn)算符。猜一猜也可以知道,若要檢查一個(gè)對(duì)象是否經(jīng)過(guò)了一個(gè)構(gòu)造函數(shù)處理千難萬(wàn)難,但是檢查它的原型是什么就容易多了,所以instanceof的實(shí)現(xiàn)從原型角度理解,就是檢查一個(gè)對(duì)象的[[prototype]]屬性是否跟特定函數(shù)的prototype一致。注意這里[[prototype]]是私有屬性,在SpiderMonkey(就是Firefox的JS引擎)中它可以用__proto__來(lái)訪問(wèn)。

原型只對(duì)于標(biāo)準(zhǔn)所描述的Object類型有意義,所以instanceof對(duì)于所有非Object對(duì)象都會(huì)得到false,而且instanceof只能判斷是否屬于某一類型,無(wú)法得到類型,但是instanceof的優(yōu)勢(shì)也是顯而易見(jiàn)的,它能夠分辨自定義的"類"構(gòu)造出的對(duì)象。

instanceof實(shí)際上是可以被欺騙的,它用到的對(duì)象私有屬性[[prototype]]固然不能更改,但函數(shù)的prototype是個(gè)共有屬性,下面代碼展示了如何欺騙instanceof

function ClassA(){};

function ClassB(){};

var o = new ClassA();//構(gòu)造一個(gè)A類的對(duì)象

ClassB.prototype = ClassA.prototype; //ClassB.prototype替換掉

alert(o instanceof ClassB)//true 欺騙成功 - -!

Object.prototype.toString——是個(gè)好方法?

Object.prototype.toString原本很難被調(diào)用到,所有的JavaScript內(nèi)置類都覆蓋了toString這個(gè)方法,而對(duì)于非內(nèi)置類構(gòu)造出的對(duì)象,Object.prototype.toString又只能得到毫無(wú)意義的[object Object]這種結(jié)果。所以相當(dāng)長(zhǎng)的一段時(shí)間內(nèi),這個(gè)函數(shù)的神奇功效都沒(méi)有被發(fā)掘出來(lái)。

在標(biāo)準(zhǔn)中,Object.prototype.toString的描述只有3句

1. 獲取this對(duì)象的[[class]]屬性

2. 通過(guò)連接三個(gè)字符串"[object ", 結(jié)果(1), 和 "]"算出一個(gè)字符串

3. 返回 結(jié)果(2).

顯而易見(jiàn),Object.prototype.toString其實(shí)只是獲取對(duì)象的[[class]]屬性而已,不過(guò)不知道是不是有意為之,所有JS內(nèi)置函數(shù)對(duì)象String Number Array RegExp……在用于new構(gòu)造對(duì)象時(shí),全都會(huì)設(shè)定[[class]]屬性,這樣[[class]]屬性就可以作為很好的判斷類型的依據(jù)。

因?yàn)镺bject.prototype.toString是取this對(duì)象屬性,所以只要用Object.prototype.toString.call或者Object.prototype.toString.apply就可以指定this對(duì)象,然后獲取類型了。

Object.prototype.toString盡管巧妙,但是卻無(wú)法獲取自定義函數(shù)構(gòu)造出對(duì)象的類型,因?yàn)樽远x函數(shù)不會(huì)設(shè)[[class]],而且這個(gè)私有屬性是無(wú)法在程序中訪問(wèn)的。Object.prototype.toString最大的優(yōu)點(diǎn)是可以讓1和new Number(1)成為同一類型的對(duì)象,大部分時(shí)候二者的使用方式是相同的。

然而值得注意的是 new Boolean(false)在參與bool運(yùn)算時(shí)與false結(jié)果剛好相反,如果這個(gè)時(shí)候把二者視為同一類型,容易導(dǎo)致難以檢查的錯(cuò)誤。

總結(jié):

為了比較上面三種類型判斷方法,我做了一張表格,大家可以由此對(duì)幾種方法有個(gè)整體比較。為了方便比較,我把幾種判斷方式得到的結(jié)果統(tǒng)一了寫法:

對(duì)象

typeof

instanceof

Object.prototype.toString

標(biāo)準(zhǔn)

"abc"

String

——

String

String

new String("abc")

Object

String

String

Object

function hello(){}

Function

Function

Function

Object

123

Number

——

Number

Number

new Number(123)

Object

Number

Number

Object

new Array(1,2,3)

Object

Array

Array

Object

new MyType()

Object

MyType

Object

Object

null

Object

——

Object

Null

undefined

Undefined

——

Object

Undefined

事實(shí)上,很難說(shuō)上面哪一種方法是更加合理的,即使是標(biāo)準(zhǔn)中的規(guī)定,也只是體現(xiàn)了JS的運(yùn)行時(shí)機(jī)制而不是最佳使用實(shí)踐。我個(gè)人觀點(diǎn)是淡化"類型"這一概念,而更多關(guān)注"我想如何使用這個(gè)對(duì)象"這種約束,使用typeof配合instanceof來(lái)檢查完全可以在需要的地方達(dá)到和強(qiáng)類型語(yǔ)言相同的效果。

附1 IEEE 754 規(guī)定的雙精度浮點(diǎn)數(shù)表示(來(lái)自中文wikipedia):

sign bit(符號(hào)): 用來(lái)表示正負(fù)號(hào)

exponent(指數(shù)): 用來(lái)表示次方數(shù)

mantissa(尾數(shù)): 用來(lái)表示精確度

clip_image001

it知識(shí)庫(kù)JavaScript中的類型,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 欧美特黄一片aa大片免费看 | 欧美人体一区二区三区 | 麻豆综合网 | 欧美精品亚洲精品日韩经典 | 婷婷色九月综合激情丁香 | 91成人高清在线播放 | 超级成人97碰碰碰免费 | 久久久久久久久久久大尺度免费视频 | 在线五月婷婷 | 久久中文字幕网 | 国产拍拍1000部ww | 国产精品欧美亚洲韩国日本久久 | 国产亚洲精品在天天在线麻豆 | 久久视热这只是精品222 | 国产男女爱视频在线观看 | 国产精品视频免费视频 | 天天天天天干 | 国产99er66在线视频 | 亚洲首页国产精品丝袜 | 午夜久久久久久网站 | 91精品国产一区二区三区左线 | 欧美特级视频 | 日本人videos18videos在线看 | 久草视频手机在线观看 | 欧美成年黄网站色高清视频 | 一区二区三区影视 | 国产大片黄在线看免费 | 精品一二三四区 | 看全大色黄大色黄大片一级爽 | 美女一级免费毛片 | 伊人色综合久久大香 | 成年女人免费又黄又爽视频 | 大学生一级毛片全黄真人 | 国产91色在线 | 久久伊人色综合 | 亚洲精品第一国产综合高清 | 日韩精品第一 | 亚洲国产成人精品91久久久 | 久久综合九九 | 成人播放 | 亚洲二区在线视频 |