在JavaScript中簡單數據類型分爲5種。分別爲 Undefined, Null,Boolean,Number,String.html
var object = null; console.log(typeof object);//object
字符串的特色:
(1).單雙引號報過均可。
(2).字符串不可變。
什麼是字符串不可變? 程序員
var str1="hello"; //開闢一份新空間 var str2="world"; //開闢一份新空間 str1=str1+str2; //由於字符串的不可變特性,改變字符串會從新開闢一份新空間,之前的那一份在一段時間後被垃圾回收機制回收。 console.log(str1); 做爲基本數據類型,字符串做爲函數參數的時候是傳值仍是傳引用呢?
若是傳值: 則必須複製一份新的字符串做爲參數。字符串若是太長的話,很明顯,浪費空間。
若是傳引用: 字符串做爲參數,若是值沒有改變,則不須要開闢新的空間。
若是值改變,又由於字符串不可變的特性而會從新開闢新的空間。
因此,字符串在做爲參數的時候是傳引用而非傳值。數組
注: 關於傳值仍是傳引用,咱們這裏參照物均爲變量自己。------詳情請看第三部分。數據結構
複雜數據類型也就是咱們常說的引用類型.引用類型是一種數據結構,其值也就是其所指向的對象。
ECMAScript提供了不少原生態的引用類型。
函數
//第一種,使用構造函數。
var object=new Object();
object.name="xxxx";
//第二種,使用字面量的建立方式,程序員更傾向於第二種
var object={
name:"xxxx"
}
(2) 對象的屬性post
Object數據類型的對象是採用鬆散的結構組織屬性的。所謂的鬆散,就是咱們所說的用鍵值對來保存對象。而鍵值對以hash表結構存儲。this
有關於對象以鍵值對存儲的文章,詳情見對象基於哈希存儲(<Key,Value>之Key篇(1)。url
Object類型的對象,屬性能夠分爲兩類:spa
a.數據屬性3d
數據屬性有四個描素其行爲的特性。
var object = { name: '張三' }; Object.defineProperty(object, 'name', { configurable: false }); delete object.name; //false
Object.defineProperty(object, 'name', {
configurable: true
}); //error:TypeError: can't redefine non-configurable property 'name'
var object = {
name: '張三',
age:18
};
Object.defineProperty(object, 'name', {
configurable: false,
enumerable: false
});
for (var property in object) {
console.log(property); //age
}
var object = { name: '張三', age: 18 }; Object.defineProperty(object, 'name', { configurable: false, enumerable: false, writable: false }); object.name = '李四'; console.log(object.name);//張三,name未被更改
var object = { name: '張三' }; Object.defineProperty(object, 'age', { configurable: false, enumerable: false, writable: false, value: 18 }); console.log(object.age);//18
b.訪問器屬性:訪問器屬性不包含數據值,但其包含getter和setter函數。其也有四個特徵值對其進行描述
var object = { name: '張三', age: 18 }; Object.defineProperty(object, 'isAdult', { configurable: false, enumerable: false, get: function () { if (this.age < 18) { return false; } else { return true; } } }); console.log(object.isAdult);//true isAdult就是一個訪問器屬性
var object = { name: '張三', age: 18 }; Object.defineProperty(object, 'changeAge', { configurable: false, enumerable: false, set: function (value) { this.age = value; } }); object.changeAge=17; console.log(object.age);//17
(3)對象的經常使用方法
//第一種 使用構造函數
var mycars=new Array() mycars[0]="Saab" mycars[1]="Volvo" mycars[2]="BMW" 或者 var mycars=new Array("Saab","Volvo","BMW") //第二種 使用數組字面量
var colors=["red","blue","green"];
var array=[]; array[100]=10; console.log(array.length);//101
array=[1,2,3,4,5];
array.length=3;
console.log(array);//1,2,3
var myDate=new Date(); //Date 對象自動使用當前的日期和時間做爲其初始值。
3.傳值和傳引用
(1)問題的起源
其實這個問題來源於C和C++,由於C或C++裏都有一個特殊的數據類型----指針,那時候所謂的傳值和傳引用是對指針來講的。
那麼針對指針來講,什麼是傳值,又什麼是傳引用呢?首先,指針做爲一種數據類型,其自己確定是佔用必定的內存空間,並且,指針同時還要指向另外一塊內存空間。
如圖所示:
針對指針來講,指針做爲一種數據類型,指針的標識符也就是其在內存中所在的地址,指針的值就是其所指向的地址。也就是說,指針值是地址。
那麼一個指針在做爲函數的參數的時候,傳給參數的究竟是指針的地址仍是指針的值呢? ----這就是傳值和傳引用問題的起源.
(2)指針的傳值和傳引用
函數的參數,在函數被調用的時候,在其函數所開闢的那個棧中是佔用必定的內存空間的,那麼這塊內存空間的值是什麼呢?
首先,先確定一點,形參的值來源確定是實參。那麼,實參給形參賦值的時候傳的是什麼呢?
(1)傳的是結構體地址,那麼就如圖所示:
若是傳的是結構體的地址,那麼也就是指針的值賦值給形參。因此,這就是咱們所謂的傳值。由圖中咱們能夠看出,若是是傳值的話,那麼做爲形參的指針和做爲實參的指針,指向的是同一個結構體。
(2)若是傳的是指針的地址,那麼指針的地址就會賦值給形參。結果,如圖所示:
對於傳引用來講,形參的值是指針的地址,那麼每次對形參的改變,其實改變的都是指針所指向的地址。而若是向取得結構體的地址,也須要經過實參的地址。
(3)JS中只存在傳值
首先須要明確一寫概念,即引用和對象的概念。
引用:也就是咱們所說的指針,其存在於棧中。
對象:也就是上圖中咱們所標記的結構體,其存在於堆中。
引用的值就是對象所在的地址。咱們用一個例子說明:
var person = { name: '張三', age: 18 }; function setName(object) { object.name = '王五'; } setName(person); console.log(person.name);//王五
依然用圖來解釋:
從上圖中咱們能夠看書,函數在傳參是,傳的是實參的值,也就是指針的值。咱們,咱們這裏理解爲傳值。
可是,換一種角度來講,把對象看成參照物,傳給形參的值就是對象的地址,也並不是對象自己,說是傳引用也不爲過。
因此,不管是傳值仍是傳引用,只要理解了便可。不必糾結於字眼。
(4)基本數據類型傳值
首先基本數據類型與引用數據類型相比的差異就是,基本數據類型保存在函數運行時的棧中,而引用數據類型的值保存在堆空間中。那麼,若是基本數據類型給形參賦值的時候是怎樣的呢?
舉個例子:
var x = 1; function add(num) { return num + 1; } add(1);
x做爲實參,num做爲函數的形參,當函數add被調用時,形參num被賦值爲實參x的值。即 num=1;結構圖以下所示:
如上如所示,此時對形參的值作任何改變均與實參無關,實參和形參是兩個互不關聯的個體。
補充一點: 字符串也是一種數據類型,那麼字符串的值保存在哪裏呢? 其做爲函數參數的時候,傳值是如何進行的呢?
字符串雖然也是一種基本數據類型,但由於其大小不固定,因此,其通常其更像與引用數據類型。但其又有其特殊性----不可變性。
什麼是字符串的不可變?
var str=""; for(var i=0;i<3;i++){ str+=i; } console.log(str);//012
看上圖程序,字符串是能夠改變的。那爲何還要說,字符串不可變呢,先別急,咱們來分析一下程序運行時內存結構圖。
看到沒有,每一次字符串值的改變,其所指向的地址都會跟着改變一次。其所說的不可變,是跟引用數據類型相比來講,引用數據類型值的改變通常是對象自己的改變,而其指向是不變的,而字符串值的改變是其指向地址的改變。因此,字符串的每一次改變都會產生垃圾,此垃圾過一段時間會被垃圾回收機制回收。
瞭解了上述的狀況,因此字符傳在做爲參數的時候,爲了節省空間,只是複製了字符串所指向的地址給形參,而形參的值若是改變了的話,由於字符串具備不可變特性,因此會從新開闢一份空間給形參。以下
var str = '你是誰?'; function change(str) { str = '我就是我了'; } change(str); console.log(str);//你是誰
字符串在Java C++中均做爲比較特殊的一種類型,JS中雖然將其看成一種基本數據類型,可是其使用時更偏向於引用數據類型,可是其又具備不可變型,才促使咱們能夠將其看成基本數據類型使用。