js的數據類型划分方式為 原始數據類型和 引用數據類型
棧: 原始數據類型(Undefined,Null,Boolean,Number、String)
堆: 引用數據類型(對象、數組、函數)
兩種類型的區別:
存儲位置不同
原始數據類型直接存儲在棧(stack)中簡單數據段,占據空間小,大小固定,屬於被頻繁使用的數據,所以存儲在棧中;
引用數據類型直接存儲在堆中,占據空間大,大小不固定,如果存儲在棧中,將會影響程序運行的性能,引用數據類型在棧中存儲了指針,該指針指向堆中該實體的起始地址,當解釋器尋找引用值時,會首先檢索其在棧中的地址,取得地址后,從堆中獲得實體。
傳值方式不同
按值傳遞(call by value)是最常用的求值策略:函數的形參是被調用時所傳實參的副本。修改形參的值並不會影響實參。
按引用傳遞(call by reference)時,函數的形參接收實參的隱式引用,而不再是副本。這意味着函數形參的值如果被修改,實參也會被修改。同時兩者指向相同的值。
按引用傳遞會使函數調用的追蹤更加困難,有時也會引起一些微妙的BUG。
按值傳遞由於每次都需要克隆副本,對一些復雜類型,性能較低。兩種傳值方式都有各自的問題。
舉例:
var person,name; person = 'kn'; name=person; person='黑白'; console.log(person,name,typeof person)//黑白 kn string
person的改變沒有改變name,說明 string 是按值傳遞的。賦值時創建一塊新的內存空間
1、基本數據類型:按值傳遞
不可變(immutable)性質
基本類型是不可變的(immutable),只有對象是可變的(mutable). 有時我們會嘗試“改變”字符串的內容,但在JS中,任何看似對string值的”修改”操作,實際都是創建新的string值。任何方法都無法改變一個基本類型的值,
var str = "abc"; str[0]; // "a" str[0] = "d"; console.log(str); //abc var name = 'jozo'; var upName=name.toUpperCase(); console.log(upName,name); // 輸出 'JOZO' 'jozo'
方法操作無法改變一個基本類型的值
var person = 'kn'; person.age = 24; person.method = function(){}; console.log(person.age); // undefined console.log(person.method); // undefined
2.引用類型:按引用傳遞
引用類型的值是可變的
var obj = {x : 0}; obj.x = 100; var o = obj; o.x = 1; console.log(obj.x)// 1, 被修改 o = {x:100}; //等同於重新賦值,重新開辟內存,不是修改 console.log(JSON.stringify(obj),JSON.stringify(o))//{"x":1} {"x":100} obj.x; // 1, 不會因o = {"x":100}改變
引用類型的值是同時保存在棧內存和堆內存中的對象
javascript和其他語言不同,其不允許直接訪問內存中的位置,也就是說不能直接操作對象的內存空間,那我們操作啥呢? 實際上,是操作對象的引用,
所以引用類型的值是按引用訪問的。
准確地說,引用類型的存儲需要內存的棧區和堆區(堆區是指內存里的堆內存)共同完成,棧區內存保存變量標識符和指向堆內存中該對象的指針,
也可以說是該對象在堆內存的地址。
假如有以下幾個對象:
var person1={name:"xiaoming"} var person2={name:"xiaohong"} var person3={name:"xiaoxiao"}
兩種數據類型在實參和形參中的區別
首先要明白什么實參什么是形參。
實參:可以是常量、變量、表達式、函數等, 無論實參是何種類型的量,在進行函數調用時,它們都必須具有確定的值, 以便把這些值傳送給形參。 因此應預先用賦值,輸入等辦法使實參獲得確定值。
形參:全稱為“形式參數”是在定義函數名和函數體的時候使用的參數,目的是用來接收調用該函數時傳遞的參數。
形參的作用是實現主調函數與被調函數之間的聯系,通常將函數所處理的數據,影響函數功能的因素或者函數處理的結果作為形參。
function addNum(param) //相對於addNum方法來說 param是形參 { param+=10; return param; } var num=10; var result=addNum(num); //相對於addNum方法來說 num是實參 console.log(num); //10 console.log(result);//20
上面的例子中,當將 num作為實參傳入方法 addNum是 param作為形參接受 並在方法體內使用,且num在全局中沒用改變,但當實參為引用類型時
function fun(param) //相對於fun方法來說 param是形參 { param[0]=99; return param; } var num=[10]; var result=fun(num); //相對於fun方法來說 num是實參 console.log(num[0]); //99 console.log(result);//[99]
在方法體內改變形參,將同時改變實參
來源: