編程語(yǔ)言亂燉(二)數(shù)據(jù)存儲(chǔ)與數(shù)據(jù)結(jié)構(gòu) - 草稿

信息的編碼表示

計(jì)算機(jī)要處理的信息是多種多樣的,如十進(jìn)制數(shù)扣草、文字了牛、符號(hào)、圖形辰妙、音頻鹰祸、視頻等,這些信息在人們的眼里是不同的密浑。但對(duì)于計(jì)算機(jī)來(lái)說(shuō)蛙婴,它們?cè)趦?nèi)存中都是一樣的,都是以二進(jìn)制的形式來(lái)表示尔破,說(shuō)白了就是1001 0011 0000 1011之類(lèi)的街图。
前面我們已經(jīng)講到,計(jì)算機(jī)是以二進(jìn)制的形式來(lái)存儲(chǔ)數(shù)據(jù)的懒构,它只認(rèn)識(shí)0和1兩個(gè)數(shù)字餐济,我們?cè)谄聊簧峡吹降奈淖郑诖鎯?chǔ)到內(nèi)存之前也都被轉(zhuǎn)換成了二進(jìn)制(0和1序列)胆剧⌒跄罚可想而知,特定的文字必然對(duì)應(yīng)著固定的二進(jìn)制赞赖,否則將無(wú)法轉(zhuǎn)換滚朵。那么,怎樣將文字與二進(jìn)制對(duì)應(yīng)呢前域?這就需要有一套規(guī)范辕近,計(jì)算機(jī)公司和軟件開(kāi)發(fā)者都必須遵守。

ASCII碼
我們知道匿垄,一個(gè)二進(jìn)制位(Bit)有0移宅、1兩種狀態(tài),一個(gè)字節(jié)(Byte)有8個(gè)二進(jìn)制位椿疗,有256種狀態(tài)漏峰,每種狀態(tài)對(duì)應(yīng)一個(gè)符號(hào),就是256個(gè)符號(hào)届榄,從00000000到11111111浅乔。計(jì)算機(jī)誕生于美國(guó),早期的計(jì)算機(jī)使用者大多使用英文,上世紀(jì)60年代靖苇,美國(guó)制定了一套英文字符與二進(jìn)制位的對(duì)應(yīng)關(guān)系席噩,稱(chēng)為ASCII碼,沿用至今贤壁。ASCII碼規(guī)定了128個(gè)英文字符與二進(jìn)制的對(duì)應(yīng)關(guān)系悼枢,占用一個(gè)字節(jié)(實(shí)際上只占用了一個(gè)字節(jié)的后面7位,最前面1位統(tǒng)一規(guī)定為0)脾拆。例如馒索,字母 a 的的ASCII碼為 01100001,那么你暫時(shí)可以理解為字母 a 存儲(chǔ)到內(nèi)存之前會(huì)被轉(zhuǎn)換為 01100001名船,讀取時(shí)遇到 01100001 也會(huì)轉(zhuǎn)換為 a绰上。
完整的ASCII碼表請(qǐng)查看:http://www.asciima.com/

Unicode編碼
隨著計(jì)算機(jī)的流行,使用計(jì)算機(jī)的人越來(lái)越多包帚,不僅限于美國(guó)渔期,整個(gè)世界都在使用,這個(gè)時(shí)候ASCII編碼的問(wèn)題就凸現(xiàn)出來(lái)了渴邦。ASCII編碼只占用1個(gè)字節(jié)疯趟,最多只能表示256個(gè)字符,我大中華區(qū)10萬(wàn)漢字怎么表示谋梭,日語(yǔ)韓語(yǔ)拉丁語(yǔ)怎么表示信峻?所以90年代又制定了一套新的規(guī)范,將全世界范圍內(nèi)的字符統(tǒng)一使用一種方式在計(jì)算機(jī)中表示瓮床,這就是Unicode編碼(Unique Code)盹舞,也稱(chēng)統(tǒng)一碼、萬(wàn)國(guó)碼隘庄。

Unicode 是一個(gè)很大的集合踢步,現(xiàn)在的規(guī)模可以容納100多萬(wàn)個(gè)符號(hào)丑掺,每個(gè)符號(hào)的對(duì)應(yīng)的二進(jìn)制都不一樣获印。Unicode 規(guī)定可以使用多個(gè)字節(jié)表示一個(gè)字符,例如 a 的編碼為 01100001街州,一個(gè)字節(jié)就夠了兼丰,”好“的編碼為 01011001 01111101,需要兩個(gè)字節(jié)唆缴。

為了兼容ASCII鳍征,Unicode 規(guī)定前0127個(gè)字符與ASCII是一樣的,不一樣的只是128255的這一段面徽。
如果你希望將字符轉(zhuǎn)換為Unicode編碼艳丛,請(qǐng)查看:http://tool.chinaz.com/Tools/Unicode.aspx
完整的Unicode編碼請(qǐng)查看:unicode.org

對(duì)Unicode的支持,是檢驗(yàn)現(xiàn)代編程語(yǔ)言的標(biāo)準(zhǔn)之一。

數(shù)據(jù)在內(nèi)存中的存儲(chǔ)

對(duì)于現(xiàn)代馮-諾依曼機(jī)型的計(jì)算機(jī)而言氮双,內(nèi)存就是存儲(chǔ)器旺聚,是處理器(CPU)存取數(shù)據(jù)的地方。現(xiàn)代計(jì)算機(jī)的內(nèi)存越來(lái)越大眶蕉,基本上可以運(yùn)行各種程序而不依賴(lài)外部存儲(chǔ)(硬盤(pán)等)。

數(shù)據(jù)存放在內(nèi)存中唧躲,就要在內(nèi)存中分出一個(gè)個(gè)存儲(chǔ)單元造挽,寫(xiě)入數(shù)據(jù)。這就帶來(lái)幾個(gè)問(wèn)題:?jiǎn)卧囊?guī)格(是一樣的還是不一樣的)弄痹、對(duì)這些單元如何管理(尋址饭入、垃圾回收、安全問(wèn)題等)肛真、如何操作這些單元谐丢。在現(xiàn)代計(jì)算機(jī)科學(xué)中,這些內(nèi)容被歸納為數(shù)據(jù)結(jié)構(gòu)蚓让,與算法并稱(chēng)為編程的兩大基本知識(shí)乾忱。一些大師聲稱(chēng):數(shù)據(jù)結(jié)構(gòu)比算法更重要。

在數(shù)據(jù)存儲(chǔ)方面历极,需要考量的是存取的效率窄瘟、安全性、空間占用和垃圾處理問(wèn)題趟卸。

變量和常量

變量(Variable)是程序操作的基本單位蹄葱。因?yàn)槌绦蛑幸幚泶罅繑?shù)據(jù),這些數(shù)據(jù)必須起個(gè)名字锄列,不然怎么區(qū)分呢图云?我們寫(xiě):

var a;   //這不但命名了一個(gè)變量,而且在內(nèi)存中劃分出一個(gè)空間用于存儲(chǔ)它
a = 10; //在這個(gè)空間寫(xiě)入數(shù)值10邻邮,現(xiàn)在a的值就是10

變量名不僅僅是為數(shù)據(jù)起了一個(gè)好記的名字竣况,還告訴我們數(shù)據(jù)存儲(chǔ)在哪里,使用數(shù)據(jù)時(shí),只要提供變量名即可尊残。在幾乎所有語(yǔ)言中屏箍,變量都需要先聲明再使用。當(dāng)我們聲明一個(gè)變量并賦值給它時(shí)嘀掸,就是打開(kāi)了一扇大門(mén),把我們的意念注入到計(jì)算機(jī)之中规惰。

程序中要處理各種各樣的數(shù)據(jù)〔撬現(xiàn)實(shí)生活中我們會(huì)找一個(gè)小箱子來(lái)存放物品,一來(lái)顯得不那么凌亂,二來(lái)方便以后找到揩晴。計(jì)算機(jī)也是這個(gè)道理勋陪,我們需要先在內(nèi)存中找一塊區(qū)域,規(guī)定用它來(lái)存放整數(shù)硫兰,并起一個(gè)好記的名字诅愚,方便以后查找。這塊區(qū)域就是“小箱子”劫映,我們可以把整數(shù)放進(jìn)去了违孝。

C語(yǔ)言中這樣在內(nèi)存中找一塊區(qū)域:
int a;
int又是一個(gè)新單詞,它是 Integer 的簡(jiǎn)寫(xiě)泳赋,意思是整數(shù)雌桑。a 是我們給這塊區(qū)域起的名字;當(dāng)然也可以叫其他名字祖今,例如 abc校坑、mn123 等。

這個(gè)語(yǔ)句的意思是:在內(nèi)存中找一塊區(qū)域千诬,命名為 a耍目,用它來(lái)存放整數(shù)。
注意 int 和 a 之間是有空格的大渤,它們是兩個(gè)詞制妄。也注意最后的分號(hào),int a表達(dá)了完整的意思泵三,是一個(gè)語(yǔ)句耕捞,要用分號(hào)來(lái)結(jié)束。
不過(guò)int a;僅僅是在內(nèi)存中找了一塊可以保存整數(shù)的區(qū)域烫幕,那么如何將 123俺抽、100、999 這樣的數(shù)字放進(jìn)去呢较曼?

C語(yǔ)言中這樣向內(nèi)存中放整數(shù):
a=123;
=是一個(gè)新符號(hào)磷斧,它在數(shù)學(xué)中叫“等于號(hào)”,例如 1+2=3捷犹,但在C語(yǔ)言中弛饭,這個(gè)過(guò)程叫做賦值(Assign)。賦值是指把數(shù)據(jù)放到內(nèi)存的過(guò)程萍歉。

把上面的兩個(gè)語(yǔ)句連起來(lái):
int a;
a=123;
就把 123 放到了一塊叫做 a 的內(nèi)存區(qū)域侣颂。你也可以寫(xiě)成一個(gè)語(yǔ)句:
int a=123;
a 中的整數(shù)不是一成不變的,只要我們需要枪孩,隨時(shí)可以更改憔晒。更改的方式就是再次賦值藻肄,例如:
int a=123;
a=1000;
a=9999;
第二次賦值,會(huì)把第一次的數(shù)據(jù)覆蓋(擦除)掉拒担,也就是說(shuō)嘹屯,a 中最后的值是9999,123从撼、1000 已經(jīng)不存在了州弟,再也找不回來(lái)了。

因?yàn)?a 的值可以改變低零,所以我們給它起了一個(gè)形象的名字呆馁,叫做變量(Variable)。

int a;創(chuàng)造了一個(gè)變量 a毁兆,我們把這個(gè)過(guò)程叫做變量定義。a=123;把 123 交給了變量 a阴挣,我們把這個(gè)過(guò)程叫做給變量賦值气堕;又因?yàn)槭堑谝淮钨x值,也稱(chēng)變量的初始化畔咧,或者賦初值茎芭。

你可以先定義變量,再初始化誓沸,例如:
int abc;
abc=999;
也可以在定義的同時(shí)進(jìn)行初始化梅桩,例如:
int abc=999;
這兩種方式是等價(jià)的。

變量的聲明和賦值

變量的聲明和賦值是所有程序語(yǔ)言的最基本命令拜隧。以下是各種語(yǔ)言的變量聲明和賦值語(yǔ)法:

C: 數(shù)據(jù)類(lèi)型+變量名稱(chēng)

int a;
a = 10;
int a, b, c;  //一次聲明多個(gè)變量
int a = 10;  //同時(shí)聲明和賦值

Java: 與C語(yǔ)言完全相同宿百。

JavaScript: 統(tǒng)一使用var關(guān)鍵字來(lái)聲明變量,不區(qū)分?jǐn)?shù)據(jù)類(lèi)型

var a;
a = 10;
var a = 20;    //同時(shí)聲明和賦值
var name="Gates", age=56, job="CEO";  //一條語(yǔ)句洪添,多個(gè)變量

ES6新增了let命令垦页,用來(lái)聲明變量。它的用法類(lèi)似于var
干奢,但是所聲明的變量痊焊,只在let命令所在的代碼塊內(nèi)有效。

{ let a = 10; var b = 1;}a // ReferenceError: a is not defined.b // 1

上面代碼在代碼塊之中忿峻,分別用let和var聲明了兩個(gè)變量薄啥。然后在代碼塊之外調(diào)用這兩個(gè)變量,結(jié)果let聲明的變量報(bào)錯(cuò)逛尚,var聲明的變量返回了正確的值垄惧。這表明,let聲明的變量只在它所在的代碼塊有效黑低。

Swift:類(lèi)似JavaScript赘艳,統(tǒng)一用var 聲明變量(語(yǔ)句結(jié)尾不用帶分號(hào)了)

var a = 10
var a = 1, b = 2, c = 3

與JavaScript不同酌毡,Swift是強(qiáng)類(lèi)型的語(yǔ)言,但Swift可以根據(jù)賦值自動(dòng)判斷出變量的類(lèi)型蕾管!
當(dāng)你聲明常量或者變量的時(shí)候可以加上類(lèi)型標(biāo)注(type annotation)枷踏,說(shuō)明常量或者變量中要存儲(chǔ)的值的類(lèi)型。如果要添加類(lèi)型標(biāo)注掰曾,需要在常量或者變量名后面加上一個(gè)冒號(hào)和空格旭蠕,然后加上類(lèi)型名稱(chēng)。
這個(gè)例子給welcomeMessage變量添加了類(lèi)型標(biāo)注旷坦,表示這個(gè)變量可以存儲(chǔ)String類(lèi)型的值:

var welcomeMessage: String

聲明中的冒號(hào)代表著“是...類(lèi)型”掏熬,所以這行代碼可以被理解為:“聲明一個(gè)類(lèi)型為String,名字為welcomeMessage的變量秒梅∑旆遥”“類(lèi)型為String”的意思是“可以存儲(chǔ)任意String類(lèi)型的值±κ瘢”
welcomeMessage變量現(xiàn)在可以被設(shè)置成任意字符串:

welcomeMessage = "Hello"

你可以在一行中定義多個(gè)同樣類(lèi)型的變量疮丛,用逗號(hào)分割,并在最后一個(gè)變量名之后添加類(lèi)型標(biāo)注:

var red, green, blue: Double

常量的聲明和賦值

實(shí)踐中辆它,有些數(shù)值我們不希望它的值變化(否則容易出錯(cuò))誊薄,我們可以把它定義為常量(constant), 如C語(yǔ)言中

#define Pi 3.14

就把Pi固定為3.14锰茉,如果以后我們不小心對(duì)Pi重新賦值呢蔫,編譯器就會(huì)報(bào)錯(cuò)。這減少了出錯(cuò)的可能飒筑。因此片吊,一種編程語(yǔ)言應(yīng)該區(qū)分變量和常量。常量在程序運(yùn)行過(guò)程中主要有2個(gè)作用:

  1. 代表常數(shù)协屡,便于程序的修改(例如:圓周率的值)定鸟;
  2. 增強(qiáng)程序的可讀性(例如:常量UP、DOWN著瓶、LEFT和RIGHT分辨代表上下左右联予,其數(shù)值分別是1、2材原、3和4)沸久。

C語(yǔ)言使用上述預(yù)處理命令來(lái)定義常量 。這在C語(yǔ)言中稱(chēng)為“符號(hào)常量”余蟹,意思時(shí)它的主要用法在于用一個(gè)符號(hào)來(lái)替代一個(gè)值或文本卷胯。在程序中所有出現(xiàn)Pi的地方在編譯時(shí)都會(huì)被3.14所代替。

Java中威酒,定義常量只需要在前面添加關(guān)鍵字final即可窑睁。在Java編碼規(guī)范中挺峡,要求常量名必須大寫(xiě)。
則常量的語(yǔ)法格式如下:
final 數(shù)據(jù)類(lèi)型 常量名稱(chēng) = 值担钮;
final 數(shù)據(jù)類(lèi)型 常量名稱(chēng)1 = 值1橱赠, 常量名稱(chēng)2 = 值2,……常量名稱(chēng)n = 值n箫津;
例如:
final double PI = 3.14狭姨;
final char MALE=‘M’,F(xiàn)EMALE=‘F’苏遥;
在Java語(yǔ)法中饼拍,常量也可以首先聲明,然后再進(jìn)行賦值田炭,但是只能賦值一次师抄,示例代碼如下:
final int UP;
UP = 1教硫;

JavaScript:
ES6新增了const關(guān)鍵字用來(lái)聲明常量司澎。一旦聲明,常量的值就不能改變栋豫。

'use strict';
const PI = 3.1415;
PI = 3;// TypeError: "PI" is read-only

上面代碼表明改變常量的值會(huì)報(bào)錯(cuò)。注意谚殊,如果是常規(guī)模式丧鸯,對(duì)常量賦值不會(huì)報(bào)錯(cuò),但也是無(wú)效的嫩絮。

const PI = 3.1415;
PI = 3; // 常規(guī)模式時(shí)丛肢,重新賦值無(wú)效,但不報(bào)錯(cuò)

const聲明的變量不得改變值剿干,這意味著蜂怎,const一旦聲明變量,就必須立即初始化置尔,不能留到以后賦值杠步。

Swift:使用let命令聲明常量并賦值
let a = 10

變量和常量的命名

變量不僅代表著我們的輸入,也代表著程序運(yùn)行的各種狀態(tài)榜轿。因此幽歼,變量的名字非常重要。起名字往往是程序員最傷腦筋的一件事谬盐。清晰代表變量用途的名字讓程序一目了然甸私,但太長(zhǎng)又不好記不好寫(xiě)。

名字并不是語(yǔ)法所規(guī)定的飞傀,但現(xiàn)代編程者趨向于按照共同的規(guī)則:用寧肯較長(zhǎng)的有意義的名字皇型,駝峰拼寫(xiě)法诬烹;首字母小寫(xiě);常量大寫(xiě)弃鸦。

在Swift中绞吁,你可以用任何你喜歡的字符作為常量和變量名,包括 Unicode 字符:
let π = 3.14159
let 你好 = "你好世界"
let = "dogcow"
常量與變量名不能包含數(shù)學(xué)符號(hào)寡键,箭頭掀泳,保留的(或者非法的)Unicode 碼位,連線與制表符西轩。也不能以數(shù)字開(kāi)頭员舵,但是可以在常量與變量名的其他地方包含數(shù)字。當(dāng)然藕畔,最好還是使用英文字母作為變量和常量的名字马僻。

綜上所述,Swift的var注服、let表示法最優(yōu)雅韭邓,JavaScript的var、const也還行溶弟。

作用域

變量的作用域是指哪個(gè)范圍內(nèi)變量的聲明有效女淑。一般分為全局變量和局部變量。全局變量在整個(gè)源文件中有效辜御,一般在函數(shù)外定義鸭你,又稱(chēng)為外部變量。 外部變量可加強(qiáng)函數(shù)模塊之間的數(shù)據(jù)聯(lián)系(比如共用的數(shù)據(jù))擒权,但是又使函數(shù)要依賴(lài)這些變量袱巨,因而使得函數(shù)的獨(dú)立性降低。從模塊化程序設(shè)計(jì)的觀點(diǎn)來(lái)看這是不利的碳抄,
因此在不必要時(shí)盡量不要使用全局變量愉老。

局部變量也稱(chēng)為內(nèi)部變量。局部變量是在函數(shù)內(nèi)作定義說(shuō)明的剖效。其作用域僅限于函數(shù)內(nèi)嫉入, 離開(kāi)該函數(shù)后再使用這種變量是非法的。

C語(yǔ)言明確區(qū)分全局變量和局部變量璧尸。在函數(shù)中聲明的都是局部變量劝贸,在函數(shù)外聲明的是全局變量(最好加extern)顶考。但在函數(shù)內(nèi)使用外部變量時(shí)要加以說(shuō)明蜜唾。

int vs(int l,int w) 
{ 
  extern int h;   //說(shuō)明這里引用外部變量
  int v; 
  v=l*w*h; 
  return v; 
}
main()
{ 
  extern int w,h;
  int l=5; 
  printf("v=%d",vs(l,w)); 
} 
int l=3,w=4,h=5; 

Java:
大多數(shù)其他計(jì)算機(jī)語(yǔ)言定義了兩大類(lèi)作用域:全局和局部别垮。然而崎淳,這些傳統(tǒng)型的作用域不適合Java 的嚴(yán)格的面向?qū)ο蟮哪P湍旱摹.?dāng)然將一個(gè)變量定義為全局變量是可行的监署,但這是例外而不是規(guī)則藏研。在Java 中2個(gè)主要的作用域是通過(guò)類(lèi)和方法定義的孽锥。盡管類(lèi)的作用域和方法的作用域的區(qū)別有點(diǎn)人為劃定。因?yàn)轭?lèi)的作用域有若干獨(dú)特的特點(diǎn)和屬性引有,而且這些特點(diǎn)和屬性不能應(yīng)用到方法定義的作用域瓣颅,這些差別還是很有意義的。因?yàn)橛胁顒e譬正,類(lèi)(以及在其內(nèi)定義的變量)的作用域?qū)⒈煌七t到第6章當(dāng)討論類(lèi)時(shí)再來(lái)討論宫补。到現(xiàn)在為止,我們將僅僅考慮由方法或在一個(gè)方法內(nèi)定義的作用域曾我。
方法定義的作用域以它的左大括號(hào)開(kāi)始粉怕。但是,如果該方法有參數(shù)抒巢,那么它們也被包括在該方法的作用域中贫贝。可認(rèn)為它們與方法中其他變量的作用域一樣蛉谜。
作為一個(gè)通用規(guī)則稚晚,在一個(gè)作用域中定義的變量對(duì)于該作用域外的程序是不可見(jiàn)(即訪問(wèn))的。因此型诚,當(dāng)你在一個(gè)作用域中定義一個(gè)變量時(shí)客燕,你就將該變量局部化并且保護(hù)它不被非授權(quán)訪問(wèn)和/或修改。實(shí)際上狰贯,作用域規(guī)則為封裝提供了基礎(chǔ)也搓。
作用域可以進(jìn)行嵌套。例如每次當(dāng)你創(chuàng)建一個(gè)程序塊暮现,你就創(chuàng)建了一個(gè)新的嵌套的作用域。這樣楚昭,外面的作用域包含內(nèi)部的作用域栖袋。這意味著外部作用域定義的對(duì)象對(duì)于內(nèi)部作用域中的程序是可見(jiàn)的。但是抚太,反過(guò)來(lái)就是錯(cuò)誤的塘幅。內(nèi)部作用域定義的對(duì)象對(duì)于外部是不可見(jiàn)的。
為理解嵌套作用域的效果尿贫,考慮下面的程序:

// Demonstrate block scope.
class Scope {
  public static void main(String args[])
  {
    int x; // known to all code within main
    x = 10;
    if(x == 10) 
    { // start new scope
      int y = 20; // known only to this block
                      // x and y both known here.
      System.out.println("x and y: " + x + " " + y);
      x = y * 2;
    }
   // y = 100; // Error! y not known here
   // x is still known here.
   System.out.println("x is " + x);
  }
}

正如注釋中說(shuō)明的那樣电媳,在方法main() 的開(kāi)始定義了變量x,因此它對(duì)于main() 中的所有的隨后的代碼都是可見(jiàn)的庆亡。在if程序塊中定義了變量y匾乓。因?yàn)橐粋€(gè)塊定義一個(gè)作用域,y 僅僅對(duì)在它的塊以?xún)?nèi)的其他代碼可見(jiàn)又谋。這就是在它的塊之外的程序行y=100; 被注釋掉的原因拼缝。如果你將該行前面的注釋符號(hào)去掉娱局,編譯程序時(shí)就會(huì)出現(xiàn)錯(cuò)誤,因?yàn)樽兞縴在它的程序塊之外是不可見(jiàn)的咧七。在if程序塊中可以使用變量x衰齐,因?yàn)閴K(即一個(gè)嵌套作用域)中的程序可以訪問(wèn)被其包圍作用域中定義的變量。
另一個(gè)需要記住的重要之處是:變量在其作用域內(nèi)被創(chuàng)建继阻,離開(kāi)其作用域時(shí)被撤消耻涛。
這意味著一個(gè)變量一旦離開(kāi)它的作用域,將不再保存它的值了瘟檩。因此抹缕,在一個(gè)方法內(nèi)定義的變量在幾次調(diào)用該方法之間將不再保存它們的值。同樣芒帕,在塊內(nèi)定義的變量在離開(kāi)該塊時(shí)也將丟棄它的值歉嗓。因此,一個(gè)變量的生存期就被限定在它的作用域中背蟆。
如果一個(gè)聲明定義包括一個(gè)初始化鉴分,那么每次進(jìn)入聲明它的程序塊時(shí),該變量都要被重新初始化带膀。例如志珍,考慮這個(gè)程序:

// Demonstrate lifetime of a variable.
class LifeTime {
  public static void main(String args[]) 
  {
    int x;
    for(x = 0; x < 3; x++)
   {
      int y = -1; // y is initialized each time block is  enter   
      System.out.println("y is: " + y); // this always prints -1
      y = 100;
      System.out.println("y is now: " + y);
    }
  }
}

該程序運(yùn)行的輸出如下:
y is: -1
y is now: 100
y is: -1
y is now: 100
y is: -1
y is now: 100
可以看到,每次進(jìn)入內(nèi)部的for循環(huán)垛叨,y都要被重新初始化為-1伦糯。即使它隨后被賦值為100,該值還是被丟棄了嗽元。
最后一點(diǎn):盡管程序塊能被嵌套敛纲,你不能將內(nèi)部作用域聲明的變量與其外部作用域聲明的變量重名。在這一點(diǎn)上剂癌,Java 不同于C和C++淤翔。

JavaScript:
傳統(tǒng)的JS語(yǔ)法中最被人詬病的一點(diǎn)就是依賴(lài)于全局變量,在聲明局部變量是一定要使用var語(yǔ)句佩谷,否則會(huì)視為對(duì)全局變量的引用旁壮。看下面代碼:

/*  錯(cuò)誤修改了全局變量  */  
var scope = "global";  
function checkScope(){  
      scope = "local";  
      document.write(scope);  
}  
checkScope();           //輸出"local"  
document.write(scope);  //輸出"local"

Javascript沒(méi)有塊級(jí)作用域谐檀,函數(shù)中聲明的變量在整個(gè)函數(shù)中都是有定義的抡谐。有可能導(dǎo)致內(nèi)層變量覆蓋外層變量:

/*  變量提升  */  
var scope = "global";  
function checkScope() {  
  document.write(scope);  //語(yǔ)句1  
  var scope = "local";    //語(yǔ)句2  
  document.write(scope);  //語(yǔ)句3
}  
checkScope();           //輸出"undefined  、local"  

如果沒(méi)有語(yǔ)句2和3桐猬,語(yǔ)句1將輸出“global”麦撵。由于語(yǔ)句2(var scope = "local";)聲明的變量在整個(gè)checkScope函數(shù)作用域內(nèi)都有效,因此在語(yǔ)句1(**document.write(scope); **)執(zhí)行的時(shí)scope引用的是局部變量,而此時(shí)局部變量scope尚未定義厦坛,所以輸出”undefined”五垮。因此一個(gè)好的編程習(xí)慣是將所有的變量聲明集中起來(lái)放在函數(shù)的開(kāi)頭。

ES5只有全局作用域和函數(shù)作用域杜秸,沒(méi)有塊級(jí)作用域放仗,這帶來(lái)很多不合理的場(chǎng)景。第一種場(chǎng)景撬碟,內(nèi)層變量可能會(huì)覆蓋外層變量诞挨。如上面的例子。第二種場(chǎng)景呢蛤,用來(lái)計(jì)數(shù)的循環(huán)變量泄露為全局變量惶傻。

var s = 'hello';
for (var i = 0; i < s.length; i++){ 
  console.log(s[i]);
}
console.log(i); // 5

上面代碼中,變量i只用來(lái)控制循環(huán)其障,但是循環(huán)結(jié)束后银室,它并沒(méi)有消失,泄露成了全局變量励翼。

ES6新增的let命令實(shí)際上為JavaScript新增了塊級(jí)作用域蜈敢。只要用花括號(hào)括起的代碼段就是一個(gè)塊級(jí)作用域。

{ 
  let a = 10; 
  var b = 1;
}
a // ReferenceError: a is not defined.
b // 1

上面代碼在代碼塊之中汽抚,分別用let和var聲明了兩個(gè)變量抓狭。然后在代碼塊之外調(diào)用這兩個(gè)變量,結(jié)果let聲明的變量報(bào)錯(cuò)造烁,var聲明的變量返回了正確的值否过。這表明,let聲明的變量只在它所在的代碼塊有效惭蟋。

for循環(huán)的計(jì)數(shù)器苗桂,就很合適使用let命令。

for(let i = 0; i < arr.length; i++){}
console.log(i)//ReferenceError: i is not defined

上面代碼的計(jì)數(shù)器i告组,只在for循環(huán)體內(nèi)有效煤伟。

ES6允許塊級(jí)作用域的任意嵌套。
內(nèi)層作用域可以定義外層作用域的同名變量惹谐。

{{{{ let insane = 'Hello World';
   {let insane = 'Hello World';}
}}}};

const的作用域與let命令相同:只在聲明所在的塊級(jí)作用域內(nèi)有效持偏。
因此驼卖,使用ES6氨肌,最好用let聲明變量。

數(shù)據(jù)類(lèi)型

從C語(yǔ)言開(kāi)始酌畜,為了節(jié)約空間和便于管理怎囚,把存儲(chǔ)數(shù)據(jù)的單元規(guī)范為幾種“數(shù)據(jù)類(lèi)型”。每種數(shù)據(jù)類(lèi)型都有一些相對(duì)應(yīng)的操作。如果一種類(lèi)型的數(shù)據(jù)要執(zhí)行另外類(lèi)型的操作恳守,比如考婴,將數(shù)字連接在一起,就要先進(jìn)行數(shù)據(jù)類(lèi)型轉(zhuǎn)換催烘。數(shù)據(jù)類(lèi)型則指明了數(shù)據(jù)的長(zhǎng)度和處理方式沥阱。所以諸如int n、char c伊群、float money這樣的形式就確定了數(shù)據(jù)在內(nèi)存中的所有要素考杉。C語(yǔ)言提供的多種數(shù)據(jù)類(lèi)型讓程序更加靈活和高效,同時(shí)也增加了學(xué)習(xí)成本舰始。而有些編程語(yǔ)言崇棠,例如PHP、JavaScript等丸卷,在定義變量時(shí)不需要指明數(shù)據(jù)類(lèi)型枕稀,編譯器會(huì)根據(jù)賦值情況自動(dòng)推演出數(shù)據(jù)類(lèi)型,更加智能谜嫉。除了C語(yǔ)言萎坷,Java、C++骄恶、C#等在定義變量時(shí)也必須指明數(shù)據(jù)類(lèi)型食铐,這樣的編程語(yǔ)言稱(chēng)為強(qiáng)類(lèi)型語(yǔ)言。而PHP僧鲁、JavaScript等在定義變量時(shí)不必指明數(shù)據(jù)類(lèi)型虐呻,編譯系統(tǒng)會(huì)自動(dòng)推演,這樣的編程語(yǔ)言稱(chēng)為弱類(lèi)型語(yǔ)言寞秃。強(qiáng)類(lèi)型語(yǔ)言一旦確定了數(shù)據(jù)類(lèi)型斟叼,就不能再賦給其他類(lèi)型的數(shù)據(jù),除非對(duì)數(shù)據(jù)類(lèi)型進(jìn)行轉(zhuǎn)換春寿。弱類(lèi)型語(yǔ)言沒(méi)有這種限制朗涩,一個(gè)變量,可以先賦給一個(gè)整數(shù)绑改,然后再賦給一個(gè)字符串谢床。最后需要說(shuō)明的是:數(shù)據(jù)類(lèi)型只在定義變量時(shí)指明,而且必須指明厘线;使用變量時(shí)無(wú)需再指明识腿,因?yàn)榇藭r(shí)的數(shù)據(jù)類(lèi)型已經(jīng)確定了。

那么造壮,到底強(qiáng)類(lèi)型好還是弱類(lèi)型好呢渡讼?強(qiáng)類(lèi)型語(yǔ)言安全性高,程序執(zhí)行效率高,節(jié)省內(nèi)存空間成箫,但編碼是需指明類(lèi)型和進(jìn)行轉(zhuǎn)換展箱。弱類(lèi)型編碼方便,但需要編譯器判斷蹬昌,執(zhí)行效率低些混驰,內(nèi)存占用多。從“盡量讓機(jī)器干活”的角度皂贩,還是弱類(lèi)型好些账胧。

C語(yǔ)言的基本數(shù)據(jù)類(lèi)型###

** 整數(shù)
計(jì)算機(jī)最基本的工作是處理數(shù)字和數(shù)學(xué)計(jì)算。整數(shù)的處理是其中最基本的先紫。從c時(shí)代起治泥,整數(shù)的表示和處理就有一套規(guī)范。

C語(yǔ)言中有三種整數(shù)類(lèi)型遮精,分別為 short居夹、int 和 long。int 稱(chēng)為整型本冲,short 稱(chēng)為短整型准脂,long 稱(chēng)為長(zhǎng)整型,它們的長(zhǎng)度(所占字節(jié)數(shù))關(guān)系為:short <= int <= long它們具體占用幾個(gè)字節(jié)C語(yǔ)言并沒(méi)有規(guī)定檬洞,C語(yǔ)言只做了寬泛的限制:short 至少占用2個(gè)字節(jié)狸膏。int 建議為一個(gè)機(jī)器字長(zhǎng)。32位環(huán)境下機(jī)器字長(zhǎng)為4字節(jié)添怔,64位環(huán)境下機(jī)器字長(zhǎng)為8字節(jié)湾戳。short 的長(zhǎng)度不能大于 int,long 的長(zhǎng)度不能小于 int广料。這就意味著砾脑,short 并不一定真的”短“,long 也并不一定真的”長(zhǎng)“艾杏,它們有可能和 int 占用相同的字節(jié)數(shù)韧衣。決定整數(shù)長(zhǎng)度的因素很多,包括硬件(CPU和數(shù)據(jù)總線)购桑、操作系統(tǒng)畅铭、編譯器等。在16位環(huán)境下勃蜘,short 為2個(gè)字節(jié)硕噩,int 為2個(gè)字節(jié),long 為4個(gè)字節(jié)元旬。16位環(huán)境多用于單片機(jī)和低級(jí)嵌入式系統(tǒng)榴徐,在PC和服務(wù)器上基本都看不到了。對(duì)于32位的 Windows匀归、Linux 和 OS X坑资,short 為2個(gè)字節(jié),int 為4個(gè)字節(jié)穆端,long 也為4個(gè)字節(jié)袱贮。PC和服務(wù)器上的32位系統(tǒng)占有率也在慢慢下降,嵌入式系統(tǒng)使用32位越來(lái)越多体啰。在64位環(huán)境下攒巍,不同的操作系統(tǒng)會(huì)有不同的結(jié)果,如下所示(長(zhǎng)度以字節(jié)計(jì)):

操作系統(tǒng) short int long
Win64 2 4 4
類(lèi)Unix系統(tǒng)(包括 Unix荒勇、Linux、OS X、BSD棚辽、Solaris 等) 2 4 8

獲取某個(gè)數(shù)據(jù)類(lèi)型的長(zhǎng)度可以使用 sizeof 操作符

符號(hào)位
在數(shù)學(xué)中浇坐,數(shù)字有正負(fù)之分。在C語(yǔ)言中也是一樣仅偎,short跨蟹、int、long 都可以帶上符號(hào)橘沥,例如:
short a = -10; //負(fù)數(shù)
int b = +10; //正數(shù)
long c = (-9) + (+12); //負(fù)數(shù)和正數(shù)相加
如果不帶正負(fù)號(hào)窗轩,默認(rèn)就是正數(shù)。
在符號(hào)位中座咆,用0表示正數(shù)痢艺,用1表示負(fù)數(shù)。例如 short 類(lèi)型的 -10介陶、+16 在內(nèi)存中的表示如下:


如果不希望設(shè)置符號(hào)位腹备,可以在數(shù)據(jù)類(lèi)型前面加 unsigned,如下所示:unsigned short a = 12;
unsigned int b = 1002;
unsigned long c = 9892320;

這樣斤蔓,short植酥、int、long 中就沒(méi)有符號(hào)位了弦牡,所有的位都用來(lái)表示數(shù)值友驮。也就意味著,使用了 unsigned 只能表示正數(shù)驾锰,不能表示負(fù)數(shù)了卸留。

取值范圍和數(shù)據(jù)溢出
short、int椭豫、long 占用的字節(jié)數(shù)不同耻瑟,所能表示的數(shù)值范圍也不同旨指。以32位平臺(tái)為例,下面是它們的取值范圍:

數(shù)據(jù)類(lèi)型 所占字節(jié) 取值范圍
short 2 -32768~32767
unsigned short 2 0~65535
int 4 -2147483648~2147483647(±21億)
unsigned int 4 0~4294967295(42億)
long 4 -2147483648~2147483647
unsigned long 4 0~4294967295

當(dāng)數(shù)值過(guò)大或過(guò)小時(shí)喳整,有限的幾個(gè)字節(jié)就不能表示谆构,就會(huì)發(fā)生溢出。發(fā)生溢出時(shí)框都,最高位會(huì)被截去搬素。請(qǐng)看下面的例子:

#include <stdio.h>
int main()
{
  unsigned int a = 0x100000000;
  printf("a=%u\n", a);
  return 0;
}

運(yùn)行結(jié)果:a=0變量 a 為 int 類(lèi)型,占用4個(gè)字節(jié)(32位)魏保,能表示的最大值為 0xFFFFFFFF熬尺,而 0x100000000 = 0xFFFFFFFF + 1,占用33位谓罗,已超出 a 所能表示的最大值粱哼,會(huì)發(fā)生溢出,最高位被截去檩咱,剩下的32位都是0皂吮。也就是說(shuō),在 a 被輸出前税手,其值已經(jīng)變成了 0蜂筹。

各種整數(shù)的輸出
在使用 printf 輸出整數(shù)時(shí),不同的控制字符會(huì)有不同的輸出格式芦倒。1) 輸出 int 使用%d艺挪,輸出 short 使用 %hd,輸出 long 使用 %ld兵扬。2) 輸出無(wú)符號(hào)數(shù)使用%u麻裳。3) 輸出十進(jìn)制使用%d,輸出八進(jìn)制使用%o器钟,輸出十六進(jìn)制使用%x或%X津坑。如果希望帶上前綴,可以加#傲霸,例如 %#d疆瑰、%#o、%#x昙啄、%#X穆役。

小數(shù)
在計(jì)算機(jī)中表示小數(shù)是一件很麻煩的事,這是二進(jìn)制本身的特點(diǎn)決定的梳凛。C語(yǔ)言證明了這一點(diǎn)耿币。

C語(yǔ)言中小數(shù)(又稱(chēng)為浮點(diǎn)數(shù))的數(shù)據(jù)類(lèi)型為 float 或 double:float 稱(chēng)為單精度浮點(diǎn)數(shù),double 稱(chēng)為雙精度浮點(diǎn)數(shù)韧拒。不像整數(shù)淹接,小數(shù)的長(zhǎng)度始終是固定的十性,float 占用4個(gè)字節(jié),double 占用8個(gè)字節(jié)塑悼。

C語(yǔ)言在內(nèi)部采用指數(shù)形式表示小數(shù)劲适。正負(fù)號(hào)、指數(shù)(n)拢肆、尾數(shù)(a) 是變化的,需要占用內(nèi)存空間來(lái)表示靖诗。float郭怪、double 在內(nèi)存中的形式如下所示:



輸出 float 使用 %f 控制符,輸出 double 使用 %lf 控制符刊橘。

#include <stdio.h>
#include <stdlib.h>
int main()
{
  float a=128.101;
  float b=0.302f;
  float c=1.23002398f;
  double d=123;
  double e = 78.429;
  printf("a=%f \nb=%f \nc=%f \nd=%lf \ne=%lf\n", a, b, c, d, e);
  system("pause");
  return 0;
}

對(duì)代碼的說(shuō)明:1) %f 默認(rèn)保留六位小數(shù)鄙才,不足六位以 0 補(bǔ)齊,超過(guò)六位按四舍五入截?cái)唷?) 將整數(shù)賦值給 float 變量時(shí)會(huì)轉(zhuǎn)換為小數(shù)促绵。3) 小數(shù)默認(rèn)為 double 類(lèi)型攒庵,加上后綴f才是float類(lèi)型。4) 由于內(nèi)存有限败晴,小數(shù)的精度受限浓冒,所以輸出 a 時(shí)只能獲得一個(gè)近似數(shù)。

字符和字符串
在人機(jī)交互的方式中尖坤,自然語(yǔ)言無(wú)疑是最自然的方式稳懒,而通過(guò)文本交互又是使用自然語(yǔ)言與機(jī)器對(duì)話(huà)的最基本形式,這就涉及字符串的處理慢味。因此场梆,對(duì)任何編程語(yǔ)言,對(duì)字符串的處理是非常重要的纯路。

恰恰或油,字符串在機(jī)器中的表示和處理又是非常復(fù)雜的一件事。人類(lèi)語(yǔ)言使用了多種多樣的字符(包括標(biāo)點(diǎn)符號(hào))驰唬,字符串本身的長(zhǎng)度又不固定顶岸,字符串的操作又很多樣,所以對(duì)編程語(yǔ)言來(lái)說(shuō)叫编,處理好字符串是很考驗(yàn)功力的蜕琴。

在C語(yǔ)言中,根本就沒(méi)有字符串這種數(shù)據(jù)類(lèi)型宵溅。C語(yǔ)言中只有字符(char)這種數(shù)據(jù)類(lèi)型凌简,占用一個(gè)字節(jié),可以存放本地字符集(一般就是ASCII字符集)中的一個(gè)字符恃逻,表示為char c = 'a'雏搂。char 變量在內(nèi)存中存儲(chǔ)的是字符對(duì)應(yīng)的 ASCII 碼值藕施。如果以 %c 輸出,會(huì)根據(jù) ASCII 碼表轉(zhuǎn)換成對(duì)應(yīng)的字符凸郑;如果以 %d 輸出裳食,那么還是整數(shù)。C語(yǔ)言還定義了一些轉(zhuǎn)義字符芙沥,如诲祸,用\n表示換行符,用\r表示回車(chē)符等而昨。

C語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供的輸入輸出模型非常簡(jiǎn)單救氯,都是按照字符流的方式處理,每次讀/寫(xiě)一個(gè)字符歌憨,如getchar和putchar函數(shù)着憨。C語(yǔ)言將字符串看做字符數(shù)組,用數(shù)組的線性存儲(chǔ)模式存儲(chǔ)字符串务嫡,除了字符甲抖,最后還要存一個(gè)\n。為了用變量表示字符串心铃,可以用數(shù)組的指針准谚。可以借助下面的形式將字符串賦值給變量:
char variableName = "string";
char和
是固定的形式去扣,variableNmae 為變量名稱(chēng)氛魁,"string" 是要賦值的字符串。
字符串使用示例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c = '@';
char *str = "This is a string.";
printf("char: %c\n", c);
printf("string1: %s\n", str);
//也可以直接輸出字符串
printf("string2: %s\n", "This is another string.");
system("pause");
return 0;
}

運(yùn)行結(jié)果:char: @string1: This is a string.string2: This is another string.
C89標(biāo)準(zhǔn)中沒(méi)有定義布爾類(lèi)型厅篓;C99中增加了_Bool類(lèi)型秀存。
_Bool型變量實(shí)際上只是一個(gè)整數(shù)類(lèi)型,
但是羽氮,_Bool只能被賦值為0或1或链,凡是不為0的整數(shù)都被轉(zhuǎn)變?yōu)?。

C語(yǔ)言中還有一些復(fù)合類(lèi)型档押,如數(shù)組澳盐、結(jié)構(gòu)、聯(lián)合等令宿,不作為基本數(shù)據(jù)類(lèi)型在這里描述叼耙。

JAVA的基本數(shù)據(jù)類(lèi)型###

Java的基本數(shù)據(jù)類(lèi)型就是內(nèi)置數(shù)據(jù)類(lèi)型(除此之外還有引用數(shù)據(jù)類(lèi)型)。
Java語(yǔ)言提供了八種基本類(lèi)型粒没。六種數(shù)字類(lèi)型(四個(gè)整數(shù)型筛婉,兩個(gè)浮點(diǎn)型),一種字符類(lèi)型癞松,還有一種布爾型爽撒。

  • byte:
    byte數(shù)據(jù)類(lèi)型是8位入蛆、有符號(hào)的,以二進(jìn)制補(bǔ)碼表示的整數(shù)硕勿;
    最小值是-128(-2^7)哨毁;
    最大值是127(2^7-1);
    默認(rèn)值是0源武;
    byte類(lèi)型用在大型數(shù)組中節(jié)約空間扼褪,主要代替整數(shù),因?yàn)閎yte變量占用的空間只有int類(lèi)型的四分之一粱栖;
    例子:byte a = 100话浇,byte b = -50。

  • short:
    short數(shù)據(jù)類(lèi)型是16位查排、有符號(hào)的以二進(jìn)制補(bǔ)碼表示的整數(shù)
    最小值是-32768(-2^15)凳枝;
    最大值是32767(2^15 - 1)抄沮;
    Short數(shù)據(jù)類(lèi)型也可以像byte那樣節(jié)省空間跋核。一個(gè)short變量是int型變量所占空間的二分之一;
    默認(rèn)值是0叛买;
    例子:short s = 1000砂代,short r = -20000。

  • int:
    int數(shù)據(jù)類(lèi)型是32位率挣、有符號(hào)的以二進(jìn)制補(bǔ)碼表示的整數(shù)刻伊;
    最小值是-2,147,483,648(-2^31);
    最大值是2,147,485,647(2^31 - 1)椒功;
    一般地整型變量默認(rèn)為int類(lèi)型捶箱;
    默認(rèn)值是0;
    例子:int a = 100000, int b = -200000动漾。

  • long:
    long數(shù)據(jù)類(lèi)型是64位丁屎、有符號(hào)的以二進(jìn)制補(bǔ)碼表示的整數(shù);
    最小值是-9,223,372,036,854,775,808(-2^63)旱眯;
    最大值是9,223,372,036,854,775,807(2^63 -1)晨川;
    這種類(lèi)型主要使用在需要比較大整數(shù)的系統(tǒng)上;
    默認(rèn)值是0L删豺;
    例子: long a = 100000L共虑,Long b = -200000L。

  • float:
    float數(shù)據(jù)類(lèi)型是單精度呀页、32位妈拌、符合IEEE 754標(biāo)準(zhǔn)的浮點(diǎn)數(shù);
    float在儲(chǔ)存大型浮點(diǎn)數(shù)組的時(shí)候可節(jié)省內(nèi)存空間蓬蝶;
    默認(rèn)值是0.0f供炎;
    浮點(diǎn)數(shù)不能用來(lái)表示精確的值渴逻,如貨幣;
    例子:float f1 = 234.5f音诫。
    最小值:Float.MIN_VALUE=1.4E-45
    最大值:Float.MAX_VALUE=3.4028235E38

  • double:
    double數(shù)據(jù)類(lèi)型是雙精度惨奕、64位、符合IEEE 754標(biāo)準(zhǔn)的浮點(diǎn)數(shù)竭钝;
    浮點(diǎn)數(shù)的默認(rèn)類(lèi)型為double類(lèi)型梨撞;
    double類(lèi)型同樣不能表示精確的值,如貨幣香罐;
    默認(rèn)值是0.0d卧波;
    例子:double d1 = 123.4。
    最小值:Double.MIN_VALUE=4.9E-324
    最大值:Double.MAX_VALUE=1.7976931348623157E308
    Float和Double的最小值和最大值都是以科學(xué)記數(shù)法的形式輸出的庇茫,結(jié)尾的"E+數(shù)字"表示E之前的數(shù)字要乘以10的多少倍港粱。比如3.14E3就是3.14×1000=3140,3.14E-3就是3.14/1000=0.00314旦签。

  • boolean:Java中引入了布爾類(lèi)型查坪。
    boolean數(shù)據(jù)類(lèi)型表示一位的信息;
    只有兩個(gè)取值:true和false宁炫;
    這種類(lèi)型只作為一種標(biāo)志來(lái)記錄true/false情況偿曙;
    默認(rèn)值是false;
    例子:boolean one = true羔巢。

  • char:
    char類(lèi)型是一個(gè)單一的16位Unicode字符望忆;
    最小值是’\u0000’(即為0);
    最大值是’\uffff’(即為65,535)竿秆;
    char數(shù)據(jù)類(lèi)型可以?xún)?chǔ)存任何字符启摄;
    例子:char letter = ‘A’。

在Java中字符串屬于對(duì)象幽钢,Java提供了String類(lèi)來(lái)創(chuàng)建和操作字符串歉备。

總的來(lái)講,Java的數(shù)據(jù)類(lèi)型比較齊整嚴(yán)謹(jǐn)搅吁,支持的數(shù)值范圍也足夠大威创。

實(shí)際上,JAVA中還存在另外一種基本類(lèi)型void谎懦,它也有對(duì)應(yīng)的包裝類(lèi) java.lang.Void肚豺,不過(guò)我們無(wú)法直接對(duì)它們進(jìn)行操作。

JavaScript的數(shù)據(jù)類(lèi)型###

作為弱類(lèi)型語(yǔ)言的代表界拦,JavaScript不強(qiáng)調(diào)變量的“類(lèi)型”吸申,實(shí)際上,你可以隨時(shí)給變量賦予任何類(lèi)型:無(wú)論數(shù)字、字母還是字符串截碴、布爾值梳侨。

var x // x 為 undefined
x = 6; // x 為數(shù)字
x = "Bill"; // x 為字符串
x = 34.00; //小數(shù)
x =123e-5; // 0.00123
x = true

事實(shí)上,JavaScript是使用了對(duì)象表示一切: Number 對(duì)象表示數(shù)字日丹。String(字符串)對(duì)象表示字符和字符串涣易。每種對(duì)象有不同的方法壳炎,所以有時(shí)還要用Number()渠概、 toString()等方法轉(zhuǎn)換马绝。

數(shù)字對(duì)象
JavaScript 只有一種數(shù)字類(lèi)型。
可以使用也可以不使用小數(shù)點(diǎn)來(lái)書(shū)寫(xiě)數(shù)字束凑。
實(shí)例
var pi=3.14; // 使用小數(shù)點(diǎn)var x=34; // 不使用小數(shù)點(diǎn)
極大或極小的數(shù)字可通過(guò)科學(xué)(指數(shù))計(jì)數(shù)法來(lái)寫(xiě):
實(shí)例
var y=123e5; // 12300000var z=123e-5; // 0.00123

所有 JavaScript 數(shù)字均為 64 位
JavaScript 不是類(lèi)型語(yǔ)言晒旅。與許多其他編程語(yǔ)言不同,JavaScript 不定義不同類(lèi)型的數(shù)字汪诉,比如整數(shù)废恋、短、長(zhǎng)扒寄、浮點(diǎn)等等鱼鼓。
JavaScript 中的所有數(shù)字都存儲(chǔ)為根為 10 的 64 位(8 比特),浮點(diǎn)數(shù)旗们。

精度
整數(shù)(不使用小數(shù)點(diǎn)或指數(shù)計(jì)數(shù)法)最多為 15 位(十兆級(jí))蚓哩。
小數(shù)的最大位數(shù)是 17构灸,但是浮點(diǎn)運(yùn)算并不總是 100% 準(zhǔn)確:
實(shí)例
0.2 + 0.1 = 0.30000000000000004

八進(jìn)制和十六進(jìn)制
如果前綴為 0上渴,則 JavaScript 會(huì)把數(shù)值常量解釋為八進(jìn)制數(shù),如果前綴為 0 和 "x"喜颁,則解釋為十六進(jìn)制數(shù)稠氮。
實(shí)例
var y=0377;var z=0xFF;
提示:絕不要在數(shù)字前面寫(xiě)零,除非您需要進(jìn)行八進(jìn)制轉(zhuǎn)換半开。

數(shù)字屬性和方法
屬性:
MAX VALUE
MIN VALUE
NEGATIVE INFINITIVE
POSITIVE INFINITIVE
NaN
prototype
constructor

方法:
toExponential()
toFixed()
toPrecision()
toString()
valueOf()

字符串(String) 對(duì)象描述
字符串是 JavaScript 的一種基本的數(shù)據(jù)類(lèi)型隔披。
String 對(duì)象的 length 屬性聲明了該字符串中的字符數(shù)。
String 類(lèi)定義了大量操作字符串的方法寂拆,例如從字符串中提取字符或子串奢米,或者檢索字符或子串。
需要注意的是纠永,JavaScript 的字符串是不可變的(immutable)鬓长,String 類(lèi)定義的方法都不能改變字符串的內(nèi)容。像 String.toUpperCase() 這樣的方法尝江,返回的是全新的字符串涉波,而不是修改原始字符串。
在較早的 Netscape 代碼基的 JavaScript 實(shí)現(xiàn)中(例如 Firefox 實(shí)現(xiàn)中),字符串的行為就像只讀的字符數(shù)組啤覆。例如苍日,從字符串 s 中提取第三個(gè)字符,可以用 s[2] 代替更加標(biāo)準(zhǔn)的 s.charAt(2)窗声。此外相恃,對(duì)字符串應(yīng)用 for/in 循環(huán)時(shí),它將枚舉字符串中每個(gè)字符的數(shù)組下標(biāo)(但要注意笨觅,ECMAScript 標(biāo)準(zhǔn)規(guī)定豆茫,不能枚舉 length 屬性)。因?yàn)樽址臄?shù)組行為不標(biāo)準(zhǔn)屋摇,所以應(yīng)該避免使用它揩魂。

ES6加強(qiáng)了對(duì)Unicode的支持,并且擴(kuò)展了字符串對(duì)象炮温。
ES6提供了二進(jìn)制和八進(jìn)制數(shù)值的新的寫(xiě)法火脉,分別用前綴0b(或0B)和0o(或0O)表示。
0b111110111 === 503 // true
0o767 === 503 // true

ES6在Number對(duì)象上柒啤,新提供了Number.isFinite()和Number.isNaN()兩個(gè)方法倦挂,用來(lái)檢查Infinite和NaN這兩個(gè)特殊值。

Number.EPSILON
ES6在Number對(duì)象上面担巩,新增一個(gè)極小的常量Number.EPSILON
方援。
Number.EPSILON// 2.220446049250313e-16Number.EPSILON.toFixed(20)// '0.00000000000000022204'

引入一個(gè)這么小的量的目的,在于為浮點(diǎn)數(shù)計(jì)算涛癌,設(shè)置一個(gè)誤差范圍犯戏。我們知道浮點(diǎn)數(shù)計(jì)算是不精確的。
0.1 + 0.2// 0.300000000000000040.1 + 0.2 - 0.3// 5.551115123125783e-175.551115123125783e-17.toFixed(20)// '0.00000000000000005551'

但是如果這個(gè)誤差能夠小于Number.EPSILON
拳话,我們就可以認(rèn)為得到了正確結(jié)果先匪。
5.551115123125783e-17 < Number.EPSILON// true

因此,Number.EPSILON
的實(shí)質(zhì)是一個(gè)可以接受的誤差范圍弃衍。
function withinErrorMargin (left, right) { return Math.abs(left - right) < Number.EPSILON}withinErrorMargin(0.1 + 0.2, 0.3)// truewithinErrorMargin(0.2 + 0.2, 0.3)// false

上面的代碼為浮點(diǎn)數(shù)運(yùn)算呀非,部署了一個(gè)誤差檢查函數(shù)。
JavaScript能夠準(zhǔn)確表示的整數(shù)范圍在-253到253之間(不含兩個(gè)端點(diǎn))镜盯,超過(guò)這個(gè)范圍岸裙,無(wú)法精確表示這個(gè)值。
Math.pow(2, 53) // 90071992547409929007199254740992 // 90071992547409929007199254740993 // 9007199254740992Math.pow(2, 53) === Math.pow(2, 53) + 1// true

上面代碼中速缆,超出2的53次方之后降允,一個(gè)數(shù)就不精確了。
ES6引入了Number.MAX_SAFE_INTEGER
和Number.MIN_SAFE_INTEGER
這兩個(gè)常量激涤,用來(lái)表示這個(gè)范圍的上下限拟糕。這可以用來(lái)預(yù)先檢查參與運(yùn)算的數(shù)值判呕,避免超出范圍。

Swift的基本數(shù)據(jù)類(lèi)型###

類(lèi)型標(biāo)注
我們知道送滞,Swift中用var聲明變量侠草,用let聲明常量,如果賦給初始值犁嗅,系統(tǒng)會(huì)自動(dòng)判斷出數(shù)據(jù)類(lèi)型边涕。
如果開(kāi)始不便賦初始值,當(dāng)你聲明常量或者變量的時(shí)候可以加上類(lèi)型標(biāo)注(type annotation)褂微,說(shuō)明常量或者變量中要存儲(chǔ)的值的類(lèi)型功蜓。如果要添加類(lèi)型標(biāo)注,需要在常量或者變量名后面加上一個(gè)冒號(hào)和空格宠蚂,然后加上類(lèi)型名稱(chēng)式撼。
這個(gè)例子給welcomeMessage變量添加了類(lèi)型標(biāo)注,表示這個(gè)變量可以存儲(chǔ)String類(lèi)型的值:

var welcomeMessage: String

聲明中的冒號(hào)代表著“是...類(lèi)型”求厕,所以這行代碼可以被理解為:
“聲明一個(gè)類(lèi)型為String著隆,名字為welcomeMessage的變量⊙窖ⅲ”
“類(lèi)型為String”的意思是“可以存儲(chǔ)任意String類(lèi)型的值美浦。”
變量現(xiàn)在可以被設(shè)置成任意字符串:

  welcomeMessage = "Hello"

你可以在一行中定義多個(gè)同樣類(lèi)型的變量项栏,用逗號(hào)分割浦辨,并在最后一個(gè)變量名之后添加類(lèi)型標(biāo)注:

var red, green, blue: Double

注意:一般來(lái)說(shuō)你很少需要寫(xiě)類(lèi)型標(biāo)注。如果你在聲明常量或者變量的時(shí)候賦了一個(gè)初始值沼沈,Swift可以推斷出這個(gè)常量或者變量的類(lèi)型流酬。在上面的例子中,沒(méi)有給welcomeMessage賦初始值庆冕,所以變量welcomeMessage的類(lèi)型是通過(guò)一個(gè)類(lèi)型標(biāo)注指定的康吵,而不是通過(guò)初始值推斷的劈榨。

類(lèi)型安全和類(lèi)型推斷
Swift 是一個(gè)類(lèi)型安全(type safe)的語(yǔ)言访递。類(lèi)型安全的語(yǔ)言可以讓你清楚地知道代碼要處理的值的類(lèi)型。如果你的代碼需要一個(gè)String
同辣,你絕對(duì)不可能不小心傳進(jìn)去一個(gè)Int
拷姿。
由于 Swift 是類(lèi)型安全的,所以它會(huì)在編譯你的代碼時(shí)進(jìn)行類(lèi)型檢查(type checks)旱函,并把不匹配的類(lèi)型標(biāo)記為錯(cuò)誤响巢。這可以讓你在開(kāi)發(fā)的時(shí)候盡早發(fā)現(xiàn)并修復(fù)錯(cuò)誤。
當(dāng)你要處理不同類(lèi)型的值時(shí)棒妨,類(lèi)型檢查可以幫你避免錯(cuò)誤踪古。然而含长,這并不是說(shuō)你每次聲明常量和變量的時(shí)候都需要顯式指定類(lèi)型。如果你沒(méi)有顯式指定類(lèi)型伏穆,Swift 會(huì)使用類(lèi)型推斷(type inference)來(lái)選擇合適的類(lèi)型拘泞。有了類(lèi)型推斷,編譯器可以在編譯代碼的時(shí)候自動(dòng)推斷出表達(dá)式的類(lèi)型枕扫。原理很簡(jiǎn)單陪腌,只要檢查你賦的值即可。
因?yàn)橛蓄?lèi)型推斷烟瞧,和 C 或者 Objective-C 比起來(lái) Swift 很少需要聲明類(lèi)型诗鸭。常量和變量雖然需要明確類(lèi)型,但是大部分工作并不需要你自己來(lái)完成参滴。
當(dāng)你聲明常量或者變量并賦初值的時(shí)候類(lèi)型推斷非常有用强岸。當(dāng)你在聲明常量或者變量的時(shí)候賦給它們一個(gè)字面量(literal value 或 literal)即可觸發(fā)類(lèi)型推斷。(字面量就是會(huì)直接出現(xiàn)在你代碼中的值砾赔,比如42和3.14159请唱。)
例如,如果你給一個(gè)新常量賦值42并且沒(méi)有標(biāo)明類(lèi)型过蹂,Swift 可以推斷出常量類(lèi)型是Int十绑,因?yàn)槟憬o它賦的初始值看起來(lái)像一個(gè)整數(shù):

let meaningOfLife = 42// meaningOfLife 會(huì)被推測(cè)為 Int 類(lèi)型

同理,如果你沒(méi)有給浮點(diǎn)字面量標(biāo)明類(lèi)型酷勺,Swift 會(huì)推斷你想要的是Double

let pi = 3.14159// pi 會(huì)被推測(cè)為 Double 類(lèi)型

當(dāng)推斷浮點(diǎn)數(shù)的類(lèi)型時(shí)本橙,Swift 總是會(huì)選擇Double而不是Float。如果表達(dá)式中同時(shí)出現(xiàn)了整數(shù)和浮點(diǎn)數(shù)脆诉,會(huì)被推斷為Double類(lèi)型:

let anotherPi = 3 + 0.14159// anotherPi 會(huì)被推測(cè)為 Double 類(lèi)型

沒(méi)有顯式聲明類(lèi)型甚亭,而表達(dá)式中出現(xiàn)了一個(gè)浮點(diǎn)字面量,所以表達(dá)式會(huì)被推斷為Double類(lèi)型击胜。

幾種數(shù)值類(lèi)型

  • 整數(shù)
    整數(shù)就是沒(méi)有小數(shù)部分的數(shù)字亏狰,比如42和-23。整數(shù)可以是有符號(hào)
    (正偶摔、負(fù)暇唾、零)或者無(wú)符號(hào)(正、零)辰斋。
    Swift 提供了8策州,16,32和64位的有符號(hào)和無(wú)符號(hào)整數(shù)類(lèi)型宫仗。這些整數(shù)類(lèi)型和 C 語(yǔ)言的命名方式很像够挂,比如8位無(wú)符號(hào)整數(shù)類(lèi)型是UInt8,32位有符號(hào)整數(shù)類(lèi)型是Int32藕夫。就像 Swift 的其他類(lèi)型一樣孽糖,整數(shù)類(lèi)型采用大寫(xiě)命名法枯冈。

整數(shù)范圍
你可以訪問(wèn)不同整數(shù)類(lèi)型的min和max
屬性來(lái)獲取對(duì)應(yīng)類(lèi)型的最小值和最大值:

let minValue = UInt8.min // minValue 為 0,是 UInt8 類(lèi)型
let maxValue = UInt8.max // maxValue 為 255办悟,是 UInt8 類(lèi)型

min和max所傳回值的類(lèi)型霜幼,正是其所對(duì)的整數(shù)類(lèi)型(如上例UInt8, 所傳回的類(lèi)型是UInt8),可用在表達(dá)式中相同類(lèi)型值旁誉尖。

Int
一般來(lái)說(shuō)罪既,你不需要專(zhuān)門(mén)指定整數(shù)的長(zhǎng)度。Swift 提供了一個(gè)特殊的整數(shù)類(lèi)型Int
铡恕,長(zhǎng)度與當(dāng)前平臺(tái)的原生字長(zhǎng)相同:在32位平臺(tái)上琢感,Int和Int32
長(zhǎng)度相同。在64位平臺(tái)上探熔,Int和Int64長(zhǎng)度相同驹针。

除非你需要特定長(zhǎng)度的整數(shù),一般來(lái)說(shuō)使用Int
就夠了诀艰。這可以提高代碼一致性和可復(fù)用性柬甥。即使是在32位平臺(tái)上,Int
可以存儲(chǔ)的整數(shù)范圍也可以達(dá)到-2,147,483,648~2,147,483,647其垄,大多數(shù)時(shí)候這已經(jīng)足夠大了苛蒲。

UInt
Swift 也提供了一個(gè)特殊的無(wú)符號(hào)類(lèi)型UInt,長(zhǎng)度與當(dāng)前平臺(tái)的原生字長(zhǎng)相同:
在32位平臺(tái)上绿满,UInt和UInt32長(zhǎng)度相同臂外。在64位平臺(tái)上,UInt和UInt64長(zhǎng)度相同喇颁。
注意:盡量不要使用UInt漏健,除非你真的需要存儲(chǔ)一個(gè)和當(dāng)前平臺(tái)原生字長(zhǎng)相同的無(wú)符號(hào)整數(shù)。除了這種情況橘霎,最好使用Int蔫浆,即使你要存儲(chǔ)的值已知是非負(fù)的。統(tǒng)一使用Int可以提高代碼的可復(fù)用性姐叁,避免不同類(lèi)型數(shù)字之間的轉(zhuǎn)換瓦盛,并且匹配數(shù)字的類(lèi)型推斷。

  • 浮點(diǎn)數(shù)
    浮點(diǎn)數(shù)是有小數(shù)部分的數(shù)字七蜘,比如3.14159谭溉,0.1和-273.15。
    浮點(diǎn)類(lèi)型比整數(shù)類(lèi)型表示的范圍更大橡卤,可以存儲(chǔ)比Int
    類(lèi)型更大或者更小的數(shù)字。Swift 提供了兩種有符號(hào)浮點(diǎn)數(shù)類(lèi)型:
    Double
    表示64位浮點(diǎn)數(shù)损搬。當(dāng)你需要存儲(chǔ)很大或者很高精度的浮點(diǎn)數(shù)時(shí)請(qǐng)使用此類(lèi)型碧库。
    Float
    表示32位浮點(diǎn)數(shù)柜与。精度要求不高的話(huà)可以使用此類(lèi)型。

注意:Double精確度很高嵌灰,至少有15位數(shù)字弄匕,而Float只有6位數(shù)字。選擇哪個(gè)類(lèi)型取決于你的代碼需要處理的值的范圍沽瞭。

其他進(jìn)制的表示
整數(shù)字面量可以被寫(xiě)作:
一個(gè)十進(jìn)制數(shù)迁匠,沒(méi)有前綴
一個(gè)二進(jìn)制數(shù),前綴是0b
一個(gè)八進(jìn)制數(shù)驹溃,前綴是0o
一個(gè)十六進(jìn)制數(shù)城丧,前綴是0x

下面的所有整數(shù)字面量的十進(jìn)制值都是17:

let decimalInteger = 17
let binaryInteger = 0b10001 // 二進(jìn)制的17
let octalInteger = 0o21 // 八進(jìn)制的17
let hexadecimalInteger = 0x11 // 十六進(jìn)制的17

浮點(diǎn)字面量可以是十進(jìn)制(沒(méi)有前綴)或者是十六進(jìn)制(前綴是0x)。小數(shù)點(diǎn)兩邊必須有至少一個(gè)十進(jìn)制數(shù)字(或者是十六進(jìn)制的數(shù)字)豌鹤。十進(jìn)制浮點(diǎn)數(shù)也可以有一個(gè)可選的指數(shù)(exponent)亡哄,通過(guò)大寫(xiě)或者小寫(xiě)的 e來(lái)指定;十六進(jìn)制浮點(diǎn)數(shù)必須有一個(gè)指數(shù)布疙,通過(guò)大寫(xiě)或者小寫(xiě)的 p來(lái)指定蚊惯。
如果一個(gè)十進(jìn)制數(shù)的指數(shù)為exp,那這個(gè)數(shù)相當(dāng)于基數(shù)和10^exp的乘積:
1.25e2表示 1.25 × 10^2灵临,等于 125.0截型。
1.25e-2表示 1.25 × 10^-2,等于 0.0125儒溉。

如果一個(gè)十六進(jìn)制數(shù)的指數(shù)為exp菠劝,那這個(gè)數(shù)相當(dāng)于基數(shù)和2^exp的乘積:
0xFp2表示 15 × 2^2,等于 60.0睁搭。0xFp-2表示 15 × 2^-2赶诊,等于 3.75。

下面的這些浮點(diǎn)字面量都等于十進(jìn)制的12.1875:

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

數(shù)值類(lèi)字面量可以包括額外的格式來(lái)增強(qiáng)可讀性园骆。整數(shù)和浮點(diǎn)數(shù)都可以添加額外的零并且包含下劃線舔痪,并不會(huì)影響字面量:

let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

數(shù)值型類(lèi)型轉(zhuǎn)換
通常來(lái)講,即使代碼中的整數(shù)常量和變量已知非負(fù)锌唾,也請(qǐng)使用Int類(lèi)型锄码。總是使用默認(rèn)的整數(shù)類(lèi)型可以保證你的整數(shù)常量和變量可以直接被復(fù)用并且可以匹配整數(shù)類(lèi)字面量的類(lèi)型推斷晌涕。只有在必要的時(shí)候才使用其他整數(shù)類(lèi)型滋捶,比如要處理外部的長(zhǎng)度明確的數(shù)據(jù)或者為了優(yōu)化性能、內(nèi)存占用等等余黎。使用顯式指定長(zhǎng)度的類(lèi)型可以及時(shí)發(fā)現(xiàn)值溢出并且可以暗示正在處理特殊數(shù)據(jù)重窟。

整數(shù)轉(zhuǎn)換
不同整數(shù)類(lèi)型的變量和常量可以存儲(chǔ)不同范圍的數(shù)字。Int8
類(lèi)型的常量或者變量可以存儲(chǔ)的數(shù)字范圍是-128127惧财,而UInt8類(lèi)型的常量或者變量能存儲(chǔ)的數(shù)字范圍是0255巡扇。如果數(shù)字超出了常量或者變量可存儲(chǔ)的范圍扭仁,編譯的時(shí)候會(huì)報(bào)錯(cuò):

let cannotBeNegative: UInt8 = -1// UInt8 類(lèi)型不能存儲(chǔ)負(fù)數(shù),所以會(huì)報(bào)錯(cuò)
let tooBig: Int8 = Int8.max + 1// Int8 類(lèi)型不能存儲(chǔ)超過(guò)最大值的數(shù)厅翔,所以會(huì)報(bào)錯(cuò)

由于每種整數(shù)類(lèi)型都可以存儲(chǔ)不同范圍的值乖坠,所以你必須根據(jù)不同情況選擇性使用數(shù)值型類(lèi)型轉(zhuǎn)換。這種選擇性使用的方式刀闷,可以預(yù)防隱式轉(zhuǎn)換的錯(cuò)誤并讓你的代碼中的類(lèi)型轉(zhuǎn)換意圖變得清晰熊泵。
要將一種數(shù)字類(lèi)型轉(zhuǎn)換成另一種,你要用當(dāng)前值來(lái)初始化一個(gè)期望類(lèi)型的新數(shù)字甸昏,這個(gè)數(shù)字的類(lèi)型就是你的目標(biāo)類(lèi)型顽分。在下面的例子中,常量twoThousand
是UInt16類(lèi)型筒扒,然而常量one是UInt8類(lèi)型怯邪。它們不能直接相加,因?yàn)樗鼈冾?lèi)型不同。所以要調(diào)用UInt16(one)來(lái)創(chuàng)建一個(gè)新的UInt16數(shù)字并用one
的值來(lái)初始化,然后使用這個(gè)新數(shù)字來(lái)計(jì)算:

let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)

現(xiàn)在兩個(gè)數(shù)字的類(lèi)型都是UInt16夏醉,可以進(jìn)行相加州刽。目標(biāo)常twoThousandAndOne
的類(lèi)型被推斷為UInt16,因?yàn)樗莾蓚€(gè)UInt16值的和。
SomeType(ofInitialValue)
是調(diào)用 Swift 構(gòu)造器并傳入一個(gè)初始值的默認(rèn)方法。在語(yǔ)言?xún)?nèi)部,UInt16
有一個(gè)構(gòu)造器武氓,可以接受一個(gè)UInt8類(lèi)型的值,所以這個(gè)構(gòu)造器可以用現(xiàn)有UInt8來(lái)創(chuàng)建一個(gè)新的UInt16仇箱。注意县恕,你并不能傳入任意類(lèi)型的值,只能傳入U(xiǎn)Int16
內(nèi)部有對(duì)應(yīng)構(gòu)造器的值剂桥。不過(guò)你可以擴(kuò)展現(xiàn)有的類(lèi)型來(lái)讓它可以接收其他類(lèi)型的值(包括自定義類(lèi)型)忠烛。

整數(shù)和浮點(diǎn)數(shù)轉(zhuǎn)換
整數(shù)和浮點(diǎn)數(shù)的轉(zhuǎn)換必須顯式指定類(lèi)型:

let three = 3let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine// pi 等于 3.14159,所以被推測(cè)為 Double 類(lèi)型

這個(gè)例子中权逗,常量three的值被用來(lái)創(chuàng)建一個(gè)Double類(lèi)型的值美尸,所以加號(hào)兩邊的數(shù)類(lèi)型須相同。如果不進(jìn)行轉(zhuǎn)換斟薇,兩者無(wú)法相加师坎。浮點(diǎn)數(shù)到整數(shù)的反向轉(zhuǎn)換同樣行,整數(shù)類(lèi)型可以用Double或者Float類(lèi)型來(lái)初始化:

let integerPi = Int(pi)// integerPi 等于 3堪滨,所以被推測(cè)為 Int 類(lèi)型

當(dāng)用這種方式來(lái)初始化一個(gè)新的整數(shù)值時(shí)胯陋,浮點(diǎn)值會(huì)被截?cái)唷R簿褪钦f(shuō)4.75
會(huì)變成4,-3.9會(huì)變成-3惶岭。

注意:結(jié)合數(shù)字類(lèi)常量和變量不同于結(jié)合數(shù)字類(lèi)字面量寿弱。字面量3可以直接和字面量0.14159相加犯眠,因?yàn)閿?shù)字字面量本身沒(méi)有明確的類(lèi)型按灶。它們的類(lèi)型只在編譯器需要求值的時(shí)候被推測(cè)。

字符與字符串
字符
Swift擁有Character類(lèi)型筐咧,通過(guò)標(biāo)明一個(gè)Character類(lèi)型并用字符字面量進(jìn)行賦值鸯旁,可以建立一個(gè)獨(dú)立的字符常量或變量:

let exclamationMark: Character = "!"

字符串
Swift擁有String類(lèi)型,String是例如"hello, world"量蕊,"albatross"這樣的有序的Character(字符)類(lèi)型的值的集合铺罢。通過(guò)String類(lèi)型來(lái)表示。 一個(gè)String
的內(nèi)容可以用變量的方式讀取残炮,它包括一個(gè)Character值的集合韭赘。
您可以在您的代碼中包含一段預(yù)定義的字符串值作為字符串字面量。字符串字面量是由雙引號(hào) ("") 包裹著的具有固定順序的文本字符集势就。 字符串字面量可以用于為常量和變量提供初始值:

let someString = "Some string literal value"

注意someString常量通過(guò)字符串字面量進(jìn)行初始化泉瞻,Swift 會(huì)推斷該常量為String類(lèi)型。

初始化空字符串 (Initializing an Empty String)
要?jiǎng)?chuàng)建一個(gè)空字符串作為初始值苞冯,可以將空的字符串字面量賦值給變量袖牙,也可以初始化一個(gè)新的String。實(shí)例:

var emptyString = "" // 空字符串字面量
var anotherEmptyString = String() // 初始化方法
// 兩個(gè)字符串均為空并等價(jià)舅锄。

您可以通過(guò)檢查其Bool類(lèi)型的isEmpty屬性來(lái)判斷該字符串是否為空:

if emptyString.isEmpty {
   print("Nothing to see here")
}// 打印輸出:"Nothing to see here"

字符串可變性 (String Mutability)
您可以通過(guò)將一個(gè)特定字符串分配給一個(gè)變量(用var)來(lái)對(duì)其進(jìn)行修改鞭达,或者分配給一個(gè)常量(用let)來(lái)保證其不會(huì)被修改:

var variableString = "Horse"
variableString += " and carriage"http:// variableString 現(xiàn)在為 "Horse and carriage"
let constantString = "Highlander"constantString += " and another Highlander"http:// 這會(huì)報(bào)告一個(gè)編譯錯(cuò)誤 (compile-time error) - 常量字符串不可以被修改。

字符串是值類(lèi)型(Strings Are Value Types)
Swift 的String類(lèi)型是值類(lèi)型皇忿。 如果您創(chuàng)建了一個(gè)新的字符串畴蹭,那么當(dāng)其進(jìn)行常量、變量賦值操作鳍烁,或在函數(shù)/方法中傳遞時(shí)叨襟,會(huì)進(jìn)行值拷貝。 任何情況下老翘,都會(huì)對(duì)已有字符串值創(chuàng)建新副本芹啥,并對(duì)該新副本進(jìn)行傳遞或賦值操作。
Swift 默認(rèn)字符串拷貝的方式保證了在函數(shù)/方法中傳遞的是字符串的值铺峭。 很明顯無(wú)論該值來(lái)自于哪里墓怀,都是您獨(dú)自擁有的。 您可以確信傳遞的字符串不會(huì)被修改卫键,除非你自己去修改它傀履。
在實(shí)際編譯時(shí),Swift 編譯器會(huì)優(yōu)化字符串的使用,使實(shí)際的復(fù)制只發(fā)生在絕對(duì)必要的情況下钓账,這意味著您將字符串作為值類(lèi)型的同時(shí)可以獲得極高的性能碴犬。

您可通過(guò)for-in循環(huán)來(lái)遍歷字符串中的characters屬性來(lái)獲取每一個(gè)字符的值:

for character in "Dog!".characters { 
  print(character)
}// D// o// g// !// 

字符串可以通過(guò)傳遞一個(gè)值類(lèi)型為Character的數(shù)組作為自變量來(lái)初始化:

let catCharacters: [Character] = ["C", "a", "t", "!", ""]
let catString = String(catCharacters)
print(catString) // 打印輸出:"Cat!"

連接字符串和字符 (Concatenating Strings and Characters)
字符串可以通過(guò)加法運(yùn)算符(+)相加在一起(或稱(chēng)“連接”)創(chuàng)建一個(gè)新的字符串:

let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2// welcome 現(xiàn)在等于 "hello there"

您也可以通過(guò)加法賦值運(yùn)算符 (+=) 將一個(gè)字符串添加到一個(gè)已經(jīng)存在字符串變量上:

var instruction = "look over"
instruction += string2// instruction 現(xiàn)在等于 "look over there"

您可以用append()方法將一個(gè)字符附加到一個(gè)字符串變量的尾部:

let exclamationMark: Character = "!"
welcome.append(exclamationMark)// welcome 現(xiàn)在等于 "hello there!"

這些方法是不是看著很眼熟?嗯梆暮,Swift吸收了大量現(xiàn)代腳本語(yǔ)言的做法服协。注意: 您不能將一個(gè)字符串或者字符添加到一個(gè)已經(jīng)存在的字符變量上,因?yàn)樽址兞恐荒馨粋€(gè)字符啦粹。

字符串插值 (String Interpolation)
字符串插值是一種在字符串中插入程序表達(dá)式的方式偿荷,比起C語(yǔ)言的%輸出法,是一種非常贊的輸出結(jié)果的形式唠椭!可以在其中包含常量跳纳、變量、字面量和表達(dá)式贪嫂。 您插入的字符串字面量的每一項(xiàng)都在以反斜線為前綴的圓括號(hào)中:

let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"

在上面的例子中寺庄,multiplier作為(multiplier)被插入到一個(gè)字符串常量量中。 當(dāng)創(chuàng)建字符串執(zhí)行插值計(jì)算時(shí)此占位符會(huì)被替換為multiplier實(shí)際的值力崇。

multiplier的值也作為字符串中后面表達(dá)式的一部分斗塘。 該表達(dá)式計(jì)算Double(multiplier) * 2.5的值并將結(jié)果 (7.5) 插入到字符串中。 在這個(gè)例子中餐曹,表達(dá)式寫(xiě)為(Double(multiplier) * 2.5)并包含在字符串字面量中逛拱。

注意:
插值字符串中寫(xiě)在括號(hào)中的表達(dá)式不能包含非轉(zhuǎn)義反斜杠 (),并且不能包含回車(chē)或換行符台猴。不過(guò)朽合,插值字符串可以包含其他字面量。

字符串的操作
當(dāng)然饱狂,Swift擁有大量字符串操作方法曹步。包括插入和刪除、比較休讳、索引讲婚、前后綴、計(jì)數(shù)等俊柔。

Unicode支持
作為最現(xiàn)代化的語(yǔ)言筹麸,Swift 的String和Character類(lèi)型是完全兼容 Unicode 標(biāo)準(zhǔn)的,對(duì)Unicode的支持是所有語(yǔ)言中最完善的雏婶。
Unicode 標(biāo)量(Unicode Scalars)
Swift 的String類(lèi)型是基于 Unicode 標(biāo)量 建立的物赶。 Unicode 標(biāo)量是對(duì)應(yīng)字符或者修飾符的唯一的21位數(shù)字,例如U+0061表示小寫(xiě)的拉丁字母(LATIN SMALL LETTER A)("a")留晚,U+1F425表示小雞表情(FRONT-FACING BABY CHICK
) ("")酵紫。
字符串字面量的特殊字符 (Special Characters in String Literals)
字符串字面量可以包含以下特殊字符:
轉(zhuǎn)義字符\0
(空字符)、\
(反斜線)、\t
(水平制表符)奖地、\n
(換行符)橄唬、\r
(回車(chē)符)、"
(雙引號(hào))参歹、'
(單引號(hào))仰楚。
Unicode 標(biāo)量,寫(xiě)成\u{n}(u為小寫(xiě))泽示,其中n為任意一到八位十六進(jìn)制數(shù)且可用的 Unicode 位碼缸血。

下面的代碼為各種特殊字符的使用示例蜜氨。 wiseWords常量包含了兩個(gè)雙引號(hào)械筛。 dollarSign、blackHeart和sparklingHeart常量演示了三種不同格式的 Unicode 標(biāo)量:

let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
// "Imageination is more important than knowledge" - Enistein
let dollarSign = "\u{24}" // $, Unicode 標(biāo)量 U+0024
let blackHeart = "\u{2665}" // , Unicode 標(biāo)量 U+2665
let sparklingHeart = "\u{1F496}" // , Unicode 標(biāo)量 U+1F496

可擴(kuò)展的字形群集(Extended Grapheme Clusters)
每一個(gè) Swift 的Character類(lèi)型代表一個(gè)可擴(kuò)展的字形群飒炎。 一個(gè)可擴(kuò)展的字形群是一個(gè)或多個(gè)可生成人類(lèi)可讀的字符 Unicode 標(biāo)量的有序排列埋哟。 舉個(gè)例子,字母é可以用單一的 Unicode 標(biāo)量é(LATIN SMALL LETTER E WITH ACUTE, 或者U+00E9)來(lái)表示郎汪。然而一個(gè)標(biāo)準(zhǔn)的字母e(LATIN SMALL LETTER E或者U+0065) 加上一個(gè)急促重音(COMBINING ACTUE ACCENT)的標(biāo)量(U+0301)赤赊,這樣一對(duì)標(biāo)量就表示了同樣的字母é。 這個(gè)急促重音的標(biāo)量形象的將e轉(zhuǎn)換成了é煞赢。

在這兩種情況中抛计,字母é代表了一個(gè)單一的 Swift 的Character值,同時(shí)代表了一個(gè)可擴(kuò)展的字形群照筑。 在第一種情況吹截,這個(gè)字形群包含一個(gè)單一標(biāo)量;而在第二種情況凝危,它是包含兩個(gè)標(biāo)量的字形群:

let eAcute: Character = "\u{E9}"                         // é
let combinedEAcute: Character = "\u{65}\u{301}"     // e 后面加上  ?
// eAcute 是 é, combinedEAcute 是 e?

可擴(kuò)展的字符群集是一個(gè)靈活的方法波俄,用許多復(fù)雜的腳本字符表示單一的Character值。

字符串的 Unicode 表示形式(Unicode Representations of Strings)
當(dāng)一個(gè) Unicode 字符串被寫(xiě)進(jìn)文本文件或者其他儲(chǔ)存時(shí)蛾默,字符串中的 Unicode 標(biāo)量會(huì)用 Unicode 定義的幾種編碼格式(encoding forms)編碼懦铺。每一個(gè)字符串中的小塊編碼都被稱(chēng)代碼單元(code units)。這些包括 UTF-8 編碼格式(編碼字符串為8位的代碼單元)支鸡, UTF-16 編碼格式(編碼字符串位16位的代碼單元)冬念,以及 UTF-32 編碼格式(編碼字符串32位的代碼單元)。
Swift 提供了幾種不同的方式來(lái)訪問(wèn)字符串的 Unicode 表示形式牧挣。 您可以利用for-in來(lái)對(duì)字符串進(jìn)行遍歷急前,從而以 Unicode 可擴(kuò)展的字符群集的方式訪問(wèn)每一個(gè)Character值。
另外浸踩,能夠以其他三種 Unicode 兼容的方式訪問(wèn)字符串的值:
UTF-8 代碼單元集合 (利用字符串的utf8屬性進(jìn)行訪問(wèn))
UTF-16 代碼單元集合 (利用字符串的utf16屬性進(jìn)行訪問(wèn))
21位的 Unicode 標(biāo)量值集合叔汁,也就是字符串的 UTF-32 編碼格式 (利用字符串的unicodeScalars屬性進(jìn)行訪問(wèn))

下面由D,o,g,(DOUBLE EXCLAMATION MARK, Unicode 標(biāo)量 U+203C)和
(DOG FACE,Unicode 標(biāo)量為U+1F436)組成的字符串中的每一個(gè)字符代表著一種不同的表示:

let dogString = "Dog"
//UTF-8表示
for codeUnit in dogString.utf8 {
    print("\(codeUnit) ", terminator: "")
}
print("")
// 68 111 103 226 128 188 240 159 144 182

//UTF-16表示
for codeUnit in dogString.utf16 {
    print("\(codeUnit) ", terminator: "")
}
print("")
// 68 111 103 8252 55357 56374

for scalar in dogString.unicodeScalars {
    print("\(scalar.value) ", terminator: "")
}
print("")
// 68 111 103 8252 128054

結(jié)論

結(jié)論:無(wú)論從表達(dá)能力、方便程度据块、安全度衡量码邻,Swift在基本數(shù)據(jù)結(jié)構(gòu)方面都是最完善的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末另假,一起剝皮案震驚了整個(gè)濱河市像屋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌边篮,老刑警劉巖己莺,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異戈轿,居然都是意外死亡凌受,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)思杯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)胜蛉,“玉大人,你說(shuō)我怎么就攤上這事色乾√懿幔” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵暖璧,是天一觀的道長(zhǎng)案怯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)澎办,這世上最難降的妖魔是什么嘲碱? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮浮驳,結(jié)果婚禮上悍汛,老公的妹妹穿的比我還像新娘。我一直安慰自己至会,他們只是感情好离咐,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著奉件,像睡著了一般宵蛀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上县貌,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天术陶,我揣著相機(jī)與錄音,去河邊找鬼煤痕。 笑死梧宫,一個(gè)胖子當(dāng)著我的面吹牛接谨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播塘匣,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼脓豪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了忌卤?” 一聲冷哼從身側(cè)響起扫夜,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驰徊,沒(méi)想到半個(gè)月后笤闯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棍厂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年颗味,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勋桶。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡脱衙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出例驹,到底是詐尸還是另有隱情,我是刑警寧澤退唠,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布鹃锈,位于F島的核電站,受9級(jí)特大地震影響瞧预,放射性物質(zhì)發(fā)生泄漏屎债。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一垢油、第九天 我趴在偏房一處隱蔽的房頂上張望盆驹。 院中可真熱鬧,春花似錦滩愁、人聲如沸躯喇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)廉丽。三九已至,卻和暖如春妻味,著一層夾襖步出監(jiān)牢的瞬間正压,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工责球, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留焦履,地道東北人拓劝。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像嘉裤,于是被迫代替她去往敵國(guó)和親凿将。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容