1、基本類型:
我們知道基本的數據類型有:undefined,boolean,number,string,null.按值訪問,可操作保存在變量中的實際的值。基本類型值指的是簡單的數據段。
基本類型的值是不可變的:
在從一個變量向另一個變量賦值基本類型時,會在該變量上創建一個新值,然后再把該值復制到為新變量分配的位置上:
var a = 10;
var b = a;
a ++ ;
console.log(a); // 11
console.log(b); // 10
此時,a中保存的值為 10 ,當使用 a 來初始化 b 時,b 中保存的值也為10,但b中的10與a中的是完全獨立的,該值只是a中的值的一個副本,此后,
這兩個變量可以參加任何操作而相互不受影響。
基本類型的比較是值的比較:只要它們的值相等它們就相等。
還有下面的情況要注意哦!
var a = 1
var b = true;
console.log(a == b);//true,這是因為==是比較值相等就相等,而===是值和類型都相同時候才為true
其實這是類型轉換和 == 運算符的知識了,也就是說在用==比較兩個不同類型的變量時會進行一些類型轉換。像上面的比較先會把true轉換為數字1再和數字1進行比較,結果就是true了。 這是當比較的兩個值的類型不同的時候==運算符會進行類型轉換,但是當兩個值的類型相同的時候,
即使是==也相當於是===。 例如下面的情況
var a = 'jozo';
var b = 'jozo';
console.log(a === b);//true
假如有以下幾個基本類型的變量:
var name = 'jozo';
var city = 'guangzhou';
var age = 22;
基本類型的變量是存放在棧區的(棧區指內存里的棧內存)
棧區包括了 變量的標識符和變量的值。
2.引用類型
引用類型:引用類型有這幾種:object、Array、RegExp、Date、Function、特殊的基本包裝類型(String、Number、Boolean)以及單體內置對象(Global、Math)。
1.引用類型的值是可變的
當從一個變量向另一個變量賦值引用類型的值時,同樣也會將存儲在變量中的對象的值復制一份放到為新變量分配的空間中。前面講引用類型的時候提到,保存在變量中的是對象在堆內存中的地址,所以,與簡單賦值不同,這個值的副本實際上是一個指針,而這個指針指向存儲在堆內存的一個對象。那么賦值操作后,兩個變量都保存了同一個對象地址,則這兩個變量指向了同一個對象。因此,改變其中任何一個變量,都會相互影響:
var a = [1,2,3];
var b = a;
b.push(4);
alert(b); //[1,2,3,4]
alert(a); //[1,2,3,4] 對象類型 : 賦值不僅是值的復制,而且也是引用的傳遞
var a = [1,2,3];
var b = a;
b = [1,2,3,4];
alert(b); //[1,2,3,4]
alert(a); //[1,2,3]
因此,引用類型的賦值其實是對象保存在棧區地址指針的賦值,因此兩個變量指向同一個對象,任何的操作都會相互影響。
2.引用類型的比較是引用的比較
var person1 = '{}';
var person2 = '{}';
console.log(person1 == person2); // true
上面講基本類型的比較的時候提到了當兩個比較值的類型相同的時候,相當於是用 === ,所以輸出是true了。再看看:
var person1 = {};
var person2 = {};
console.log(person1 == person2); // false
可能你已經看出破綻了,上面比較的是兩個字符串,而下面比較的是兩個對象,為什么長的一模一樣的對象就不相等了呢?
別忘了,引用類型時按引用訪問的,換句話說就是比較兩個對象的堆內存中的地址是否相同,那很明顯,person1和person2在堆內存中地址是不同的:
所以這兩個是完全不同的對象,所以返回false;
3.引用類型的值是同時保存在棧內存和堆內存中的對象
javascript和其他語言不同,其不允許直接訪問內存中的位置,也就是說不能直接操作對象的內存空間,那我們操作啥呢? 實際上,是操作對象的引用,所以引用類型的值是按引用訪問的。准確地說,引用類型的存儲需要內存的棧區和堆區(堆區是指內存里的堆內存)共同完成,棧區內存保存變量標識符和指向堆內存中該對象的指針,也可以說是該對象在堆內存的地址。
假如有以下幾個對象:
var person1 = {name:'jozo'};
var person2 = {name:'xiaom'};
var person3 = {name:'xiaoq'};
也就是說基本類型在賦值操作后,兩個變量是相互不受影響的。
另外需要注意的是:String是一個特殊的基本數據類型
在很多語言中,String是以對象的形式表示的,但在ECMAScript里沒有沿用這種傳統,String是當作一種基本數據類型,但它是一個比較特殊的基本類型。
看上去好像String應該做為一個引用類型,可實際上它不是,因為它不是對象。那么看起來它應該是基本數據類型,應該是通值傳遞的方式來操作。
看下面例子:
var stra = "這是一個字符串";
var strb = stra;
stra = "這是另外一個字符串";
console.log(strb); // 這是一個字符串
上面例子我們看到,仿佛stra通過值傳遞的方式復制了一份給了strb。當stra改變的時候,strb並沒有改變,似乎我們已經可以下結論,String就是個基本數據類型。
可是,因為String是可以任意長度的,通過值傳遞,一個一個的復制字節顯示效率依然很低,看起來String也可以當作引用類型。
看下面例子:
var a = "myobject";
a.name = "myname";
console.log(a.name); // undefined
顯示String無法當作一個對象來處理。實際上,javascript里的String是不可以改變的,javascript也沒有提供任何一個改變字符串的方法和語法。
var a = "myobject";
a = a.substring(3,5)
console.log(a); // bj
記住這樣做,就沒有改變String字符串"myobject",只a引用了另一個字符串"bj","myobject"被回收了。
所以可以這樣講,String實際上並不符合上面兩種數據類型分類。它是具有兩方面屬性介於兩都之間的一種特殊類型。