js中值類型和引用類型的區(qū)別介紹
1.JavaScript中的變量類型有哪些?
(1)值類型(基本類型):字符串(string)、數(shù)值(number)、布爾值(boolean)、undefined、null 、symbol
(2)引用類型:對(duì)象(Object)、數(shù)組(Array)、函數(shù)(Function)
2.值類型和引用類型的區(qū)別
(1)值類型:
1、占用空間固定,保存在棧中(當(dāng)一個(gè)方法執(zhí)行時(shí),每個(gè)方法都會(huì)建立自己的內(nèi)存棧,在這個(gè)方法內(nèi)定義的變量將會(huì)逐個(gè)放入這塊棧內(nèi)存里,隨著方法的執(zhí)行結(jié)束,這個(gè)方法的內(nèi)存棧也將自然銷毀了。因此,所有在方法中定義的變量都是放在棧內(nèi)存中的;棧中存儲(chǔ)的是基礎(chǔ)變量以及一些對(duì)象的引用變量,基礎(chǔ)變量的值是存儲(chǔ)在棧中
,而引用變量存儲(chǔ)在棧中的是指向堆中的數(shù)組或者對(duì)象的地址
,這就是為何修改引用類型總會(huì)影響到其他指向這個(gè)地址的引用變量。)
2、保存與復(fù)制的是值本身
3、使用typeof檢測(cè)數(shù)據(jù)的類型
4、基本類型數(shù)據(jù)是值類型
(2)引用類型:
1、占用空間不固定,保存在堆中(當(dāng)我們?cè)诔绦蛑袆?chuàng)建一個(gè)對(duì)象時(shí),這個(gè)對(duì)象將被保存到運(yùn)行時(shí)數(shù)據(jù)區(qū)中,以便反復(fù)利用(因?yàn)閷?duì)象的創(chuàng)建成本通常較大),這個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū)就是堆內(nèi)存。堆內(nèi)存中的對(duì)象不會(huì)隨方法的結(jié)束而銷毀,即使方法結(jié)束后,這個(gè)對(duì)象還可能被另一個(gè)引用變量所引用(方法的參數(shù)傳遞時(shí)很常見),則這個(gè)對(duì)象依然不會(huì)被銷毀
,只有當(dāng)一個(gè)對(duì)象沒有任何引用變量引用它時(shí),系統(tǒng)的垃圾回收機(jī)制才會(huì)在核實(shí)的時(shí)候回收它。)
2、保存與復(fù)制的是指向?qū)ο蟮囊粋€(gè)指針
3、使用instanceof檢測(cè)數(shù)據(jù)類型
4、使用new()方法構(gòu)造出的對(duì)象是引用型
實(shí)例:
// 值類型:Number、string、bollean、undefined var a = 100 var b = a a = 200 console.log(b) // 100 保存與復(fù)制的是值本身 // 引用類型:對(duì)象、數(shù)組、函數(shù)、null(空指針) // 可以擴(kuò)展屬性 var a = {age:20} var b = a b.age = 21 console.log(a.age) // 21 // 利用typeof來(lái)區(qū)分 typeof undefined // undefined typeof 'abc' // string typeof 123 // number typeof true // boolean // typeof 區(qū)分不出來(lái)引用類型(除了函數(shù)) typeof {} // object typeof [] // object typeof null // object typeof console.log //function // 用instanceof來(lái)區(qū)分引用類型 // 如果變量是給定引用類型(根據(jù)它的原型鏈來(lái)識(shí)別)的實(shí)例,那么instanceof 操作符就會(huì)返回 true。
console.log(person instanceof Object); // 變量 person 是 Object 嗎?
console.log(colors instanceof Array); // 變量 colors 是 Array 嗎?
console.log(pattern instanceof RegExp); // 變量 pattern 是 RegExp 嗎?
3. 幾方面的區(qū)別舉例:
(1)動(dòng)態(tài)的屬性: 定義基本類型值和引用類型值的方式是類似的。但是,當(dāng)這個(gè)值保存到變量中以后,對(duì)不同類型值可以執(zhí)行的操作則大相徑庭。對(duì)于引用類型的值,我們可以為其添加屬性和方法,也可以改變和刪除其屬性和方法,但是,我們不能給基本類型的值添加屬性,只能給引用類型值動(dòng)態(tài)地添加屬性,以便將來(lái)使用。例如
var person = new Object(); person.name = "Nicholas"; alert(person.name); //"Nicholas"
(2)復(fù)制變量值: 如果從一個(gè)變量向另一個(gè)變量復(fù)制基本類型值,會(huì)在變量對(duì)象上創(chuàng)建一個(gè)新值,然后把該值復(fù)制到為新變量分配的位置上。
上述例子中,num1保存的值是5,當(dāng)使用 num1 的值來(lái)初始化 num2 時(shí),num2 中也保存了值 5。但 num2中的 5 與 num1 中的 5 是完全獨(dú)立的,該值只是 num1 中 5 的一個(gè)副本。此后,這兩個(gè)變量可以參與任何操作而不會(huì)相互影響。
var num1 = 5; var num2 = num1
復(fù)制基本類型的過(guò)程:
當(dāng)從一個(gè)變量向另一個(gè)變量復(fù)制引用類型的值時(shí),同樣也會(huì)將存儲(chǔ)在變量對(duì)象中的值復(fù)制一份放到為新變量分配的空間中。不同的是,這個(gè)值的副本實(shí)際上是一個(gè)指針,而這個(gè)指針指向存儲(chǔ)在堆中的一個(gè)對(duì)象。復(fù)制操作結(jié)束后,兩個(gè)變量實(shí)際上引用同一個(gè)對(duì)象。因此,改變其中一個(gè)變量,就會(huì)影響另外一個(gè)變量:例
var obj1 = new Object(); var obj2 = obj1; obj1.name = "Nicholas"; alert(obj2.name); //"Nicholas"
首先,變量 obj1 保存了一個(gè)對(duì)象的新實(shí)例。然后,這個(gè)值被復(fù)制到了 obj2 中;換句話說(shuō),obj1和 obj2 都指向同一個(gè)對(duì)象。這樣,當(dāng)為 obj1 添加 name 屬性后,可以通過(guò) obj2 來(lái)訪問(wèn)這個(gè)屬性,因?yàn)檫@兩個(gè)變量引用的都是同一個(gè)對(duì)象。
復(fù)制值類型的過(guò)程如下圖:
(3)傳遞參數(shù):在向參數(shù)傳遞基本類型的值時(shí),被傳遞的值會(huì)被復(fù)制給一個(gè)局部變量(即命名參數(shù),或者用ECMAScript 的概念來(lái)說(shuō),就是 arguments 對(duì)象中的一個(gè)元素)。在向參數(shù)傳遞引用類型的值時(shí),會(huì)把這個(gè)值在內(nèi)存中的地址復(fù)制給一個(gè)局部變量,因此這個(gè)局部變量的變化會(huì)反映在函數(shù)的外部。
function addTen(num) { num += 10; return num; } var count = 20; var result = addTen(count); alert(count); //20,沒有變化 alert(result); //30
在函數(shù)內(nèi)部,參數(shù) num 的值被加上了 10,但這一變化不會(huì)影響函數(shù)外部的 count 變量。參數(shù)num 與變量 count 互不相識(shí),它們僅僅是具有相同的值。
function setName(obj) { obj.name = "Nicholas"; } var person = new Object(); setName(person); alert(person.name); //"Nicholas"
為了證明對(duì)象是按值傳遞的,我們?cè)倏匆豢聪旅孢@個(gè)經(jīng)過(guò)修改的例子:
function setName(obj) { obj.name = "Nicholas"; obj = new Object(); obj.name = "Greg"; } var person = new Object(); setName(person); alert(person.name); //"Nicholas"
如果 person 是按引用傳遞的,那么 person 就會(huì)自動(dòng)被修改為指向其 name 屬性值為"Greg"的新對(duì)象。但是,當(dāng)接下來(lái)再訪問(wèn) person.name 時(shí),顯示的值仍然是"Nicholas"。
這說(shuō)明即使在函數(shù)內(nèi)部修改了參數(shù)的值,但原始的引用仍然保持未變。實(shí)際上,當(dāng)在函數(shù)內(nèi)部重寫 obj 時(shí),這個(gè)變量引用的就是一個(gè)局部對(duì)象了。而這個(gè)局部對(duì)象會(huì)在函數(shù)執(zhí)行完畢后立即被銷毀。
4. 變量計(jì)算--強(qiáng)制類型轉(zhuǎn)換
// 字符串拼接 var a = 100 + 10 //110 var b = 100 + '10' //10010 // == 運(yùn)算符 100 == '100' //true 0 == '' //true null == undefined //true // 語(yǔ)句 var a = true if(a){} var b = 100 if(b){} // 把數(shù)字轉(zhuǎn)換為true var c = '' if(c){} // 把空字符串轉(zhuǎn)換為false // 邏輯運(yùn)算 console.log(10&&0); // 0 把10轉(zhuǎn)換成true console.log('' || 'abc'); // 'abc' 把空字符串轉(zhuǎn)換為false console.log(!window.abc); // window.abc是undefined 把非undefined轉(zhuǎn)換成true //判斷一個(gè)變量會(huì)被當(dāng)做true還是false var a = 100 console.log(!!a); // true
到此這篇關(guān)于js中值類型和引用類型區(qū)別的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
判斷js中各種數(shù)據(jù)的類型方法之typeof與0bject.prototype.toString講解
提醒大家,Object.prototype.toString().call(param)返回的[object class]中class首字母是大寫,像JSON這種甚至都是大寫,所以,大家判斷的時(shí)候可以都轉(zhuǎn)換成小寫,以防出錯(cuò)2013-11-11

JavaScript學(xué)習(xí)筆記之JS函數(shù)

Javascript基礎(chǔ)教程之關(guān)鍵字和保留字匯總

JavaScript的繼承實(shí)現(xiàn)小結(jié)