第1章 原始類型和引用類型

1.原始類型和引用類型

1.1 什么是類型

原始類型 保存為簡(jiǎn)單數(shù)據(jù)值。
引用類型 保存為對(duì)象详炬,其本質(zhì)是指向內(nèi)存位置的引用魄健。

為了讓開發(fā)者能夠把原始類型和引用類型按相同的方式處理,JavaScript花費(fèi)了很大的努力來保證語言的一致性孟抗。

其他編程語言用棧存原始類型润匙,用對(duì)存儲(chǔ)引用類型诗眨。而JavaScript則完全不同:它使用一個(gè)變量對(duì)象追蹤變量的生存期。原始值被直接保存在變量對(duì)象內(nèi)孕讳,而引用值則作為一個(gè)指針保存在變量對(duì)象內(nèi)辽话,該指針指向?qū)嶋H對(duì)象在內(nèi)存中的存儲(chǔ)位置。

1.2 原始類型

原始類型代表照原樣保存的一些簡(jiǎn)單數(shù)據(jù)卫病。
JavaScript共有 5 種原始類型:

  • boolean 布爾,值為 true or false
  • number 數(shù)字典徘,值為任何整型或浮點(diǎn)數(shù)值
  • string 字符串蟀苛,值為由單引號(hào)或雙引號(hào)括住的單個(gè)字符或連續(xù)字符
  • null 空類型,僅有一個(gè)值:null
  • undefined 未定義逮诲,只有一個(gè)值:undefined(undefined會(huì)被賦給一個(gè)還沒有初始化的變量)

JavaScript和許多其他語言一樣帜平,原始類型的變量直接保存原始值(而不是一個(gè)指向?qū)ο蟮闹羔槪?/p>

var color1 = "red";
var color2 = color1;

console.log(color1); // "red"
console.log(color2); // "red"

color1 = "blue";

console.log(color1); // "blue"
console.log(color2); // "red"

鑒別原始類型

鑒別原始類型的最佳方式是使用 typeof 操作符。

console.log(typeof "Nicholas"); // "string"
console.log(typeof 10);         // "number"
console.log(typeof true);       // "boolean"
console.log(typeof undefined);  // "undefined"

至于空類型(null)則有些棘手梅鹦。

console.log(typeof null); // "object"

對(duì)于 typeof null裆甩,結(jié)果是"object"。(其實(shí)這已被設(shè)計(jì)和維護(hù)JavaScript的委員會(huì)TC39認(rèn)定是一個(gè)錯(cuò)誤齐唆。在邏輯上嗤栓,你可以認(rèn)為 null 是一個(gè)空的對(duì)象指針,所以結(jié)果為"object"箍邮,但這還是很令人困惑茉帅。)

判斷一個(gè)值是否為空類型(null)的最佳方式是直接和 null 比較:

console.log(value === null); // true or false

注意:以上這段代碼使用了三等號(hào)(全等===),因?yàn)槿忍?hào)(全等)不會(huì)將變量強(qiáng)制轉(zhuǎn)換為另一種類型锭弊。

console.log("5" == 5); // true
console.log("5" === 5); // false

console.log(undefined == null); // true
console.log(undefined === null); // false

原始方法

雖然字符串堪澎、數(shù)字和布爾值是原始類型,但是它們也擁有方法(null和undefined沒有方法)味滞。

var name = "Nicholas";
var lowercaseName = name.toLowerCase(); // 轉(zhuǎn)為小寫

var count = 10;
var fixedCount = count.toFixed(2); // 轉(zhuǎn)為10.00

var flag = true;
var stringFlag = flag.toString(); // 轉(zhuǎn)為"true"

console.log("YIBU".charAt(0)); // 輸出"Y"

盡管原始類型擁有方法樱蛤,但它們不是對(duì)象钮呀。JavaScript使它們看上去像對(duì)象一樣,以此來提高語言上的一致性體驗(yàn)昨凡。

1.3 引用類型

引用類型是指JavaScript中的對(duì)象爽醋,同時(shí)也是你在該語言中能找到最接近類的東西。
引用值是引用類型的實(shí)例土匀,也是對(duì)象的同義詞(后面將用對(duì)象指代引用值)子房。對(duì)象是屬性的無序列表。屬性包含鍵(始終是字符串)和值就轧。如果一個(gè)屬性的值是函數(shù)证杭,它就被稱為方法。除了函數(shù)可以運(yùn)行以外妒御,一個(gè)包含數(shù)組的屬性和一個(gè)包含函數(shù)的屬性沒有什么區(qū)別解愤。

創(chuàng)建對(duì)象

有時(shí)候,把JavaScript對(duì)象想象成哈希表可以幫助你更好地理解對(duì)象結(jié)構(gòu)乎莉。

Paste_Image.png

JavaScript 有好幾種方法可以創(chuàng)建對(duì)象送讲,或者說實(shí)例化對(duì)象。第一種是使用 new 操作符和構(gòu)造函數(shù)惋啃。
構(gòu)造函數(shù)就是通過 new 操作符來創(chuàng)建對(duì)象的函數(shù)——任何函數(shù)都可以是構(gòu)造函數(shù)哼鬓。根據(jù)命名規(guī)范,JavaScript中的構(gòu)造函數(shù)用首字母大寫來跟非構(gòu)造函數(shù)進(jìn)行區(qū)分边灭。

var object = new Object();

因?yàn)橐妙愋筒辉僮兞恐兄苯颖4鎸?duì)象异希,所以本例中的 object 變量實(shí)際上并不包含對(duì)象的實(shí)例,而是一個(gè)指向內(nèi)存中實(shí)際對(duì)象所在位置的指針(或者說引用)绒瘦。這是對(duì)象和原始值之間的一個(gè)基本差別称簿,原始值是直接保存在變量中。

當(dāng)你將一個(gè)對(duì)象賦值給變量時(shí)惰帽,實(shí)際是賦值給這個(gè)變量一個(gè)指針憨降。這意味著,將一個(gè)變量賦值給另外一個(gè)變量時(shí)该酗,兩個(gè)變量各獲得了一份指針的拷貝授药,指向內(nèi)存中的同一個(gè)對(duì)象。

var obj1 = new Object();
var obj2 = obj1;
Paste_Image.png

對(duì)象引用解除

JavaScript語言有垃圾收集的功能呜魄,因此當(dāng)你使用引用類型時(shí)無需擔(dān)心內(nèi)存分配烁焙。但最好在不使用對(duì)象時(shí)將其引用解除,讓垃圾收集器對(duì)那塊內(nèi)存進(jìn)行釋放耕赘。解除引用的最佳手段是將對(duì)象變量設(shè)置為 null骄蝇。

var obj1 = new Object();
// dosomething
obj1 = null; // dereference

添加刪除屬性

在JavaScript中,你可以隨時(shí)添加和刪除其屬性操骡。

var obj1 = new Object();
var obj2 = obj1;

obj1.myCustomProperty = "Awsome!";
console.log(obj2.myCustomProperty); // "Awsome!" 因?yàn)閛bj1和obj2指向同一個(gè)對(duì)象九火。

1.4 內(nèi)建類型實(shí)例化

內(nèi)建類型如下:

  • Array 數(shù)組類型赚窃,以數(shù)字為索引的一組值的有序列表
  • Date 日期和時(shí)間類型
  • Error 運(yùn)行期錯(cuò)誤類型
  • Function 函數(shù)類型
  • Object 通用對(duì)象類型
  • RegExp 正則表達(dá)式類型

可使用 new 來實(shí)例化每一個(gè)內(nèi)建引用類型:

var items = new Array();
var new = new Date();
var error = new Error("Something bad happened.");
var func = new Function("console.log('HI');");
var object = new Object();
var re = new RegExp();

字面形式

內(nèi)建引用類型有字面形式。字面形式允許你在不需要使用 new 操作符和構(gòu)造函數(shù)顯示創(chuàng)建對(duì)象的情況下生成引用值岔激。屬性的可以是標(biāo)識(shí)符或字符串(若含有空格或其他特殊字符)

var book = {
    name: "Book_name",
    year: 2016
}

上面代碼與下面這段代碼等價(jià):

var book = new Object();
book.name = "Book_name";
book.year = 2016;

雖然使用字面形式并沒有調(diào)用 new Object()勒极,但是JavaScript引擎背后做的工作和 new Object()一樣,除了沒有調(diào)用構(gòu)造函數(shù)虑鼎。其他引用類型的字面形式也是如此辱匿。

1.5 訪問屬性

可通過 .中括號(hào) 訪問對(duì)象的屬性。
中括號(hào)[]在需要?jiǎng)討B(tài)決定訪問哪個(gè)屬性時(shí)炫彩,特別有用匾七。因?yàn)槟憧梢杂?strong>變量而不是字符串字面形式來指定訪問的屬性。

1.6 鑒別引用類型

函數(shù)是最容易鑒別的引用類型江兢,因?yàn)閷?duì)函數(shù)使用 typeof 操作符時(shí)昨忆,返回"function"。

function reflect(value){
    return value;
}
console.log(typeof reflect); // "function"

對(duì)其他引用類型的鑒別則較為棘手杉允,因?yàn)閷?duì)于所有非函數(shù)的引用類型邑贴,typeof 返回 object。為了更方便地鑒別引用類型叔磷,可以使用 JavaScript 的 instanceof 操作符拢驾。

var items = [];
var obj = {};
function reflect(value){
    return value;
}

console.log(items instanceof Array); // true;
console.log(obj instanceof Object); // true;
console.log(reflect instanceof Function); // true;

instanceof 操作符可鑒別繼承類型。這意味著所有對(duì)象都是 Oject 的實(shí)例改基,因?yàn)樗幸妙愋投祭^承自 Object繁疤。

雖然 instanceof 可以鑒別對(duì)象類型(如數(shù)組),但是有一個(gè)列外寥裂。JavaScript 的值可以在同一個(gè)網(wǎng)頁的不用框架之間傳來傳去。由于每個(gè)網(wǎng)頁擁有它自己的全局上下文——Object案疲、Array以及其他內(nèi)建類型的版本封恰。所以當(dāng)你把一個(gè)對(duì)象(如數(shù)組)從一個(gè)框架傳到另外一個(gè)框架時(shí),instanceof就無法識(shí)別它褐啡。

1.8 原始封裝類型

原始封裝類型有 3 種:String诺舔、Number 和 Boolean。
當(dāng)讀取字符串备畦、數(shù)字或布爾值時(shí)低飒,原始封裝類型將被自動(dòng)創(chuàng)建。

var name = "Nicholas";
var firstChar = name.charAt(0); // "N"

這在背后發(fā)生的事情如下:

var name = "Nichola";
var temp = new String(name);
var firstChar = temp.charAt(0);
temp = null;

由于第二行把字符串當(dāng)成對(duì)象使用懂盐,JavaScript引擎創(chuàng)建了一個(gè)字符串的實(shí)體讓 charAt(0) 可以工作褥赊。字符串對(duì)象的存在僅用于該語句并在隨后銷毀(一種被稱為自動(dòng)打包的過程)。為了測(cè)試這一點(diǎn)莉恼,試著給字符串添加一個(gè)屬性看看它是不是對(duì)象拌喉。

var name = "Nicholas";
name.last = "Zakas";

console.log(name.last); // undefined;

下面是在JavaScript引擎中實(shí)際發(fā)生的事情:

var name = "Nicholas";
var temp = new String(name);
temp.last = "Zakas";
temp = null; // temporary object destroyed

var temp = new String(name);
console.log(temp.last);
temp = null;

新屬性 last 實(shí)際上是在一個(gè)立刻就被銷毀的臨時(shí)對(duì)象上而不是字符串上添加速那。之后當(dāng)你試圖訪問該屬性時(shí),另一個(gè)不同的臨時(shí)對(duì)象被創(chuàng)建尿背,而新屬性并不存在端仰。

雖然原始封裝類型會(huì)被自動(dòng)創(chuàng)建,在這些值上進(jìn)行 instanceof 檢查對(duì)應(yīng)類型的返回值卻是 false田藐。
這是因?yàn)?strong>臨時(shí)對(duì)象僅在值被讀取時(shí)創(chuàng)建荔烧。instanceof 操作符并沒有真的讀取任何東西,也就沒有臨時(shí)對(duì)象的創(chuàng)建汽久。

當(dāng)然你也可以手動(dòng)創(chuàng)建原始封裝類型鹤竭。

var str = new String("me");
str.age = 18;

console.log(typeof str); // object
console.log(str.age); // 18

如你所見,手動(dòng)創(chuàng)建原始封裝類型實(shí)際會(huì)創(chuàng)建出一個(gè) object回窘。這意味著 typeof 無法鑒別出你實(shí)際保存的數(shù)據(jù)的類型诺擅。

另外,手動(dòng)創(chuàng)建原始封裝類型和使用原始值是有一定區(qū)別的啡直。所以盡量避免使用烁涌。

var found = new Boolean(false);
if(found){
    console.log("Found"); // 執(zhí)行到了,盡管對(duì)象的值為 false
}

這是因?yàn)橐粋€(gè)對(duì)象(如 {} )在條件判斷語句中總被認(rèn)為是 true;

MDN:Any object whose value is not undefined or null, including a Boolean oject whose value is false, evaluates to true when passed to a conditional statement.

1.9 總結(jié)

第一章的東西都是我們一些比較熟悉的知識(shí)酒觅。但是也有一些需要注意的地方:

  • 正確區(qū)分原始類型和引用類型
  • 對(duì)于 5 種原始類型都可以用typeof來鑒別撮执,而空類型必須直接跟 null 進(jìn)行全等比較。
  • 函數(shù)也是對(duì)象舷丹,可用 typeof 鑒別抒钱。其它引用類型,可用 instanceof 和一個(gè)構(gòu)造函數(shù)來鑒別颜凯。(當(dāng)然可以用 Object.prototype.toString.call() 鑒別谋币,它會(huì)返回[object Array]之類的)。
  • 為了讓原始類型看上去更像引用類型症概,JavaScript提供了 3 種封裝類型蕾额。JavaScript會(huì)在背后創(chuàng)建這些對(duì)象使得你能夠像使用普通對(duì)象那樣使用原始值。但這些臨時(shí)對(duì)象在使用它們的語句結(jié)束時(shí)就立刻被銷毀彼城。雖然可手動(dòng)創(chuàng)建诅蝶,但不建議。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末募壕,一起剝皮案震驚了整個(gè)濱河市调炬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌舱馅,老刑警劉巖缰泡,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異代嗤,居然都是意外死亡匀谣,警方通過查閱死者的電腦和手機(jī)照棋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來武翎,“玉大人烈炭,你說我怎么就攤上這事”Χ瘢” “怎么了符隙?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)垫毙。 經(jīng)常有香客問我霹疫,道長(zhǎng),這世上最難降的妖魔是什么综芥? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任丽蝎,我火速辦了婚禮,結(jié)果婚禮上膀藐,老公的妹妹穿的比我還像新娘屠阻。我一直安慰自己,他們只是感情好额各,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布国觉。 她就那樣靜靜地躺著,像睡著了一般虾啦。 火紅的嫁衣襯著肌膚如雪麻诀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天傲醉,我揣著相機(jī)與錄音蝇闭,去河邊找鬼。 笑死硬毕,一個(gè)胖子當(dāng)著我的面吹牛呻引,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播昭殉,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼苞七,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼藐守!你這毒婦竟也來了挪丢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤卢厂,失蹤者是張志新(化名)和其女友劉穎乾蓬,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慎恒,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡任内,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年撵渡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片死嗦。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趋距,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出越除,到底是詐尸還是另有隱情节腐,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布摘盆,位于F島的核電站翼雀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏孩擂。R本人自食惡果不足惜狼渊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望类垦。 院中可真熱鬧狈邑,春花似錦、人聲如沸护锤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烙懦。三九已至驱入,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氯析,已是汗流浹背亏较。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掩缓,地道東北人雪情。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像你辣,于是被迫代替她去往敵國和親巡通。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

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

  • 原始類型是簡(jiǎn)單的數(shù)據(jù)值舍哄,引用類型則保存為對(duì)象宴凉,其本質(zhì)是指向內(nèi)存位置的引用。??其他編程語言用棧存儲(chǔ)原始類型表悬,用堆存...
    illuSioN4ng閱讀 355評(píng)論 1 1
  • 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的 JavaScript 類型 使用基本類型和基本包裝類型 引用類型的...
    悶油瓶小張閱讀 683評(píng)論 0 0
  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,238評(píng)論 0 4
  • 說話弥锄,穿著,寫字,無處不在向周邊的人透露著我們是一個(gè)什么樣的人籽暇。 當(dāng)然這些僅是表像温治,要知道我們的思想,行為戒悠,才是真...
    九悠閱讀 499評(píng)論 0 4
  • 她很矛盾绸狐,她不愿意好好備課惶看,好好花心思,她卻想把課上好六孵,不是卻想把課上好吧纬黎。而是,認(rèn)為自己就把課上好劫窒。 認(rèn)為自己就...
    觀照生活閱讀 168評(píng)論 0 0