JavaScript基本數據類型和引用數據類型

JavaScript基本數據類型和引用數據類型。ECMAScript包含兩種不同數據類型的值:基本類型值和引用類型值。基本類型值指的是簡單的數據段,而引用類型值那些可能有多個值構成的對象。

  在進行變量賦值時,解析器必須確定這個值是基本類型值還是引用類型值。常用的5中基本數據類型為:Undefined、Null、Boolean、Number和String。基本數據類型是按值訪問的,因為可以操作保存在變量中的實際的值。而引用類型的值是保存在內存中的對象。JavaScript不允許直接訪問內存中的位置,即不能直接操作對象的內存空間。在操作對象時,實際上是在操作對象的引用而不是實際的對象。因此,引用類型的值是按引用訪問的。

1. 動態的屬性

  對於引用類型的值,我們可以為其添加屬性和方法,也可以改變和刪除其屬性和方法。例如:

  var person = new Object();
  person.name = "John";
  alert(person.name);    //"John"

  隻要對象不被銷毀或者這個屬性不被刪除,這個屬性就一直存在。但我們不能給基本類型的值添加屬性,盡管並不會導致任何錯誤。

2. 復制變量值

  如果從一個變量向另一個變量復制基本類型的值,會在變量對象上創建一個新值,然後將該值復制到為新變量分配的位置上,例如:

  var num1 = 5;
  var num2 = num1;    //5

  下圖形象地展示瞭復制基本類型值的過程:

  當從一個變量向另一個變量復制引用類型的值時,同樣會將存儲在變量對象中的值復制一份放到為新變量分配的空間中。不同的是,這個值的副本實際上是一個指針,而這個指針指向存儲在堆中的一個對象。復制操作結束後,兩個變量實際上將引用同一個對象。因此,改變其中一個變量,就會影響另一個變量,例如:

 

  var obj1 = new Object();
  var obj2 = obj1;
  obj1.name = "John";
  alert(obj2.name);    //"John"

 

3. 傳遞參數

  ECMAScript中所有函數的參數都是按值傳遞的。把函數外部的值復制給函數內部的參數,就和把一個變量的值復制給另一個變量一樣。無論傳遞的是基本類型的值還是引用類型的值。這裡需要註意,訪問變量有按值和按引用兩種方式,但參數隻能按值傳遞。

  在向參數傳遞基本類型的值時,被傳遞的值會被復制給一個局部變量(即命名參數)。例如:

function addTen(num){
       num += 10;
       return num;          
}
var count = 20;
var result = addTen(count);
alert(count);    //20,沒有變化
alert(result);    //30

  參數實際上是函數的局部變量。參數num和變量count互不認識,它們隻是具有相同的值。假如num是按引用傳遞的,那麼count的值也會變成30,從而反應函數內部的變化。

  在向參數傳遞引用類型的值時,會把這個值在內存中的地址復制給一個局部變量,因此這個局部變量的變化會反應在函數外部。例如:

  

function setName(obj){
     obj.name = "John";
}
var person = new Object();
setName(person);
alert(person.name);    //"John"

  在這個函數內部,obj和person引用的是同一個對象。換句話說,即使這個值是按值傳遞的,obj也會按引用來訪問同一個對象。於是,在函數內容為obj添加nama屬性在函數外的person對象也有所反應,因為person指向的對象在堆內存中隻有一個,而且是全局對象。有許多開發者認為,在函數內容修改的對象會在全局作用域中反應出來,說明參數是按引用傳遞的,這個觀點其實是錯誤的,看下面的代碼:

function setName(obj){
      obj.name = "John";
      obj = new Object();
      obj.name = "Evan";
}
var person = new Object();
setName(person);
alert(person.name);    //"John"

  如果person是按引用傳遞的,那麼person就會自動被修改為指向其name屬性為"Evan"的新對象,但我們訪問person.name時發現其值仍然為"John",這說明即使在函數內部修改瞭參數的值,但原始的引用仍然保持不變。實際上,在函數內部重寫obj時,這個變量引用的就是一個局部對象瞭。而這個局部對象在函數執行完成之後會立即銷毀。

4. 檢測類型

  要檢測一個值是不是基本數據類型,typeof操作符是最佳工具。它可以檢測一個變量是字符串、數值、佈爾值還是undefined。如果一個變量是對象或null,則typeof操作符會返回object。

  但是在檢測引用類型的值時,typeof用處就不那麼大瞭,通常我們並不想知道某個值是對象,而想知道它是什麼類型的對象,此時可以使用instanceof操作符,如果變量是給定引用類型的實例,那麼instanceof操作符就會返回true。例如:

alert(person instanceof Object);    //變量person是Object嗎?
alert(colors instanceof Array);    //變量colors是Array嗎?
alert(pattern instanceof RegExp);    //變量pattern是RegExp嗎?

  所有引用類型的值都是Object的實例。因此,在檢測一個引用類型的值或Object構造函數時,instanceof都會返回true。當用instanceof操作符檢測一個基本類型的值時,都會返回false,因為基本類型不是對象。

發佈留言