1.JavaScript中的變量類型有哪些?es6
(1)值類型(基本類型):字符串(string)、數值(number)、布爾值(boolean)、undefined、null (這5種基本數據類型是按值訪問的,由於能夠操做保存在變量中的實際的值)(ECMAScript 2016新增了一種基本數據類型:symbol http://es6.ruanyifeng.com/#docs/symbol )數組
(2)引用類型:對象(Object)、數組(Array)、函數(Function)函數
2.值類型和引用類型的區別spa
(1)值類型:一、佔用空間固定,保存在棧中(當一個方法執行時,每一個方法都會創建本身的內存棧,在這個方法內定義的變量將會逐個放入這塊棧內存裏,隨着方法的執行結束,這個方法的內存棧也將天然銷燬了。所以,全部在方法中定義的變量都是放在棧內存中的;棧中存儲的是基礎變量以及一些對象的引用變量,基礎變量的值是存儲在棧中
,而引用變量存儲在棧中的是指向堆中的數組或者對象的地址
,這就是爲什麼修改引用類型總會影響到其餘指向這個地址的引用變量。)指針
二、保存與複製的是值自己code
三、使用typeof檢測數據的類型對象
四、基本類型數據是值類型blog
(2)引用類型:一、佔用空間不固定,保存在堆中(當咱們在程序中建立一個對象時,這個對象將被保存到運行時數據區中,以便反覆利用(由於對象的建立成本一般較大),這個運行時數據區就是堆內存。堆內存中的對象不會隨方法的結束而銷燬,即便方法結束後,這個對象還可能被另外一個引用變量所引用(方法的參數傳遞時很常見),則這個對象依然不會被銷燬
,只有當一個對象沒有任何引用變量引用它時,系統的垃圾回收機制纔會在覈實的時候回收它。)ip
二、保存與複製的是指向對象的一個指針內存
三、使用instanceof檢測數據類型
四、使用new()方法構造出的對象是引用型
實例:
// 值類型:Number、string、bollean、undefined var a = 100 var b = a a = 200 console.log(b) // 100 保存與複製的是值自己 // 引用類型:對象、數組、函數、null(空指針) // 能夠擴展屬性 var a = {age:20} var b = a b.age = 21 console.log(a.age) // 21
// 利用typeof來區分 typeof undefined // undefined typeof 'abc' // string typeof 123 // number typeof true // boolean // typeof 區分不出來引用類型(除了函數) typeof {} // object typeof [] // object typeof null // object typeof console.log //function
// 用instanceof來區分引用類型
// 若是變量是給定引用類型(根據它的原型鏈來識別)的實例,那麼instanceof 操做符就會返回 true。
console.log(person instanceof Object); // 變量 person 是 Object 嗎?
console.log(colors instanceof Array); // 變量 colors 是 Array 嗎?
console.log(pattern instanceof RegExp); // 變量 pattern 是 RegExp 嗎?
3. 幾方面的區別舉例:
(1)動態的屬性: 定義基本類型值和引用類型值的方式是相似的。可是,當這個值保存到變量中之後,對不一樣類型值能夠執行的操做則截然不同。對於引用類型的值,咱們能夠爲其添加屬性和方法,也能夠改變和刪除其屬性和方法,可是,咱們不能給基本類型的值添加屬性,只能給引用類型值動態地添加屬性,以便未來使用。例如
var person = new Object(); person.name = "Nicholas"; alert(person.name); //"Nicholas"
(2)複製變量值: 若是從一個變量向另外一個變量複製基本類型值,會在變量對象上建立一個新值,而後把該值複製到爲新變量分配的位置上。
var num1 = 5; var num2 = num1
上述例子中,num1保存的值是5,當使用 num1 的值來初始化 num2 時,num2 中也保存了值 5。但 num2中的 5 與 num1 中的 5 是徹底獨立的,該值只是 num1 中 5 的一個副本。此後,這兩個變量能夠參與任何操做而不會相互影響。
複製基本類型的過程:
當從一個變量向另外一個變量複製引用類型的值時,一樣也會將存儲在變量對象中的值複製一份放到爲新變量分配的空間中。不一樣的是,這個值的副本其實是一個指針,而這個指針指向存儲在堆中的一個對象。複製操做結束後,兩個變量實際上引用同一個對象。所以,改變其中一個變量,就會影響另一個變量:例
var obj1 = new Object(); var obj2 = obj1; obj1.name = "Nicholas"; alert(obj2.name); //"Nicholas"
首先,變量 obj1 保存了一個對象的新實例。而後,這個值被複制到了 obj2 中;換句話說,obj1和 obj2 都指向同一個對象。這樣,當爲 obj1 添加 name 屬性後,能夠經過 obj2 來訪問這個屬性,由於這兩個變量引用的都是同一個對象。
複製值類型的過程以下圖:
(3)傳遞參數:在向參數傳遞基本類型的值時,被傳遞的值會被複制給一個局部變量(即命名參數,或者用ECMAScript 的概念來講,就是 arguments 對象中的一個元素)。在向參數傳遞引用類型的值時,會把這個值在內存中的地址複製給一個局部變量,所以這個局部變量的變化會反映在函數的外部。
function addTen(num) { num += 10; return num; } var count = 20; var result = addTen(count); alert(count); //20,沒有變化 alert(result); //30
在函數內部,參數 num 的值被加上了 10,但這一變化不會影響函數外部的 count 變量。參數num 與變量 count 互不相識,它們僅僅是具備相同的值。
function setName(obj) { obj.name = "Nicholas"; } var person = new Object(); setName(person); alert(person.name); //"Nicholas"
爲了證實對象是按值傳遞的,咱們再看一看下面這個通過修改的例子:
function setName(obj) { obj.name = "Nicholas"; obj = new Object(); obj.name = "Greg"; } var person = new Object(); setName(person); alert(person.name); //"Nicholas"
若是 person 是按引用傳遞的,那麼 person 就會自動被修改成指向其 name 屬性值爲"Greg"的新對象。可是,當接下來再訪問 person.name 時,顯示的值仍然是"Nicholas"。
這說明即便在函數內部修改了參數的值,但原始的引用仍然保持未變。實際上,當在函數內部重寫 obj 時,這個變量引用的就是一個局部對象了。而這個局部對象會在函數執行完畢後當即被銷燬。
4. 變量計算--強制類型轉換
// 字符串拼接 var a = 100 + 10 //100 var b = 100 + '10' //10010 // == 運算符 100 == '100' //true 0 == '' //true null == undefined //true // 語句 var a = true if(a){} var b = 100 if(b){} // 把數字轉換爲true var c = '' if(c){} // 把空字符串轉換爲false // 邏輯運算 console.log(10&&0); // 0 把10轉換成true console.log('' || 'abc'); // 'abc' 把空字符串轉換爲false console.log(!window.abc); // window.abc是undefined 把非undefined轉換成true //判斷一個變量會被當作true仍是false var a = 100 console.log(!!a); // true