變量:JS的變量為松散類型(即可以用來(lái)保存任何類型的數(shù)據(jù)),換句話說(shuō)十饥,每個(gè)變量?jī)H僅是一個(gè)用于保存值的占位符而已窟勃。它由變量名和變量值組成,變量名是字符串類型逗堵,變量值不會(huì)是一個(gè)對(duì)象秉氧,而是儲(chǔ)存在棧中一個(gè)固定值,引用類型儲(chǔ)存的是一個(gè)堆內(nèi)存中的地址蜒秤。
基本類型值:在將一個(gè)保存著原始值的變量復(fù)制給另一個(gè)變量時(shí)汁咏,會(huì)將原始值的副本賦值給新變量亚斋,從此以后兩個(gè)變量時(shí)完全獨(dú)立的,他們只是擁有相同的value而已攘滩。
引用類型值:在將一個(gè)保存著對(duì)象內(nèi)存地址的變量復(fù)制給另一個(gè)變量時(shí)帅刊,會(huì)把這個(gè)內(nèi)存地址賦值給新變量,他們都指向堆內(nèi)存中同一個(gè)對(duì)象漂问,他們中任何一個(gè)改變都會(huì)反映在另一個(gè)身上(復(fù)制對(duì)象時(shí)并不會(huì)在堆內(nèi)存中新生成一個(gè)一摸一樣的對(duì)象赖瞒,只是多了一個(gè)保存指向這個(gè)對(duì)象指針的變量罷了)
形參(parameter)變量只有在被調(diào)用時(shí)才分配內(nèi)存單元,調(diào)用結(jié)束蚤假,即可釋放所分配的內(nèi)存單元冒黑,因此形參只在函數(shù)內(nèi)部有效。
實(shí)參(arguments)可以是常量勤哗、變量抡爹、表達(dá)式、函數(shù)等芒划,無(wú)論何種類型的量冬竟,在進(jìn)行函數(shù)調(diào)用時(shí),他們都必須有確定的值民逼,以便把這些參數(shù)傳送給形參泵殴。
????????EMCAScript規(guī)定在調(diào)用函數(shù)時(shí),可傳入任意數(shù)量拼苍,任意類型的參數(shù)笑诅,可以不跟函數(shù)定義時(shí)傳入的形參數(shù)量相對(duì)應(yīng)。為什么會(huì)這樣呢疮鲫?
? ??????原因就是吆你,EMACAScript中的參數(shù)在內(nèi)部是用一個(gè)數(shù)組來(lái)表示的,函數(shù)接收的始終是這個(gè)數(shù)組俊犯,而不關(guān)心包含哪些參數(shù)妇多。而且,在函數(shù)體內(nèi)也可以通過(guò)arguments這個(gè)對(duì)象來(lái)訪問(wèn)這個(gè)參數(shù)數(shù)組燕侠,從而獲取傳遞給函數(shù)的每一個(gè)參數(shù)者祖。(arguments就是一個(gè)對(duì)象--函數(shù)的一個(gè)內(nèi)部對(duì)象,和this一樣绢彤。)因此arguments看起來(lái)就像一個(gè)類數(shù)組了七问。可以用arguments[n]來(lái)訪問(wèn)各個(gè)位置的元素了.
? ??????函數(shù)內(nèi)部茫舶,有兩個(gè)特殊對(duì)象:arguments 和 this械巡。arguments是一個(gè)類數(shù)組對(duì)象,包含著傳入函數(shù)中的所有參數(shù)。該對(duì)象有一個(gè)屬性callee,該屬性是一個(gè)指針坟比,指向擁有這個(gè)arguments對(duì)象的函數(shù)芦鳍。與callee屬性對(duì)應(yīng)的就是caller屬性,arguments對(duì)象也擁有caller屬性葛账,即:arguments.caller柠衅。但在嚴(yán)格模式下訪問(wèn)它會(huì)報(bào)錯(cuò),而在非嚴(yán)格模式下這個(gè)屬性始終是undefined籍琳。該屬性主要就是為了分清arguments.caller和函數(shù)的caller屬性菲宴。函數(shù)的caller屬性指向調(diào)用該函數(shù)的外部函數(shù)。
按值傳遞:函數(shù)的形參是被調(diào)用時(shí)所傳實(shí)參的副本趋急,修改形參的值并不影響實(shí)參喝峦。(js基本類型(undefined、null呜达、boolean谣蠢、number、string)都是按值傳遞的查近,每次都需要克隆副本眉踱,對(duì)一些復(fù)雜類型,性能較低)
按引用傳遞: 函數(shù)的形參接受實(shí)參的隱式引用霜威,不再是實(shí)參的副本谈喳,函數(shù)形參的值被修改,實(shí)參也會(huì)被修改戈泼。(js對(duì)象類型(function婿禽、array、date)大猛,也叫引用類型)?引用類型在做為參數(shù)傳遞時(shí)是按共享傳遞的
共享傳遞:調(diào)用函數(shù)參數(shù)時(shí)扭倾,函數(shù)接受對(duì)象實(shí)參引用的副本(既不是按值傳遞的對(duì)象副本,也不是按引用傳遞的隱式引用胎署,和按引用傳遞的區(qū)別:在調(diào)用函數(shù)傳遞引用類型的參數(shù)時(shí)吆录,傳遞的是對(duì)象引用的副本,但是這個(gè)對(duì)象引用的副本跟原對(duì)象引用指向的是同一個(gè)地方(即該對(duì)象在內(nèi)存中存放的地址))琼牧,在共享傳遞中對(duì)函數(shù)形參的賦值,不會(huì)影響實(shí)參的值哀卫。
var foo = {name:'foo'};
function test(o){
o.name='test';
o={name:'bar'} }
test(foo);
console.log(foo);
//打印結(jié)果為:Object {name: "test"} ?
以上解釋其實(shí)不是本質(zhì)巨坊,我們繼續(xù)。
其實(shí)ECAMScript中所有函數(shù)都是按值傳遞的此改,在涉及到基本類型與引用類型時(shí)有區(qū)別是 內(nèi)存分配不同 造成的趾撵。(這里和變量復(fù)制時(shí)遵循的機(jī)制完全一樣,可以簡(jiǎn)單理解傳遞參數(shù)時(shí),就是把實(shí)參復(fù)制給形參的過(guò)程)
聲明變量時(shí)不同的內(nèi)存分配:基本類型值占调,儲(chǔ)存在棧(stack)中的簡(jiǎn)單數(shù)據(jù)段暂题,他們的值直接儲(chǔ)存在變量訪問(wèn)的位置,他們占據(jù)的空間是固定的究珊,所以將他們儲(chǔ)存在較小的內(nèi)存區(qū)域-棧中薪者,這樣儲(chǔ)存便于迅速查找變量的值。引用值:儲(chǔ)存在堆(heap)中的對(duì)象剿涮,放在變量的椦越颍空間中的值是該對(duì)象儲(chǔ)存在堆中的地址(一個(gè)指針),大小固定指向儲(chǔ)存對(duì)象的內(nèi)存地址取试,引用對(duì)象值大小會(huì)改變悬槽,所以不能把它放在棧中,否則會(huì)降低變量查詢速度瞬浓。
js中是不允許直接訪問(wèn)保存在堆內(nèi)存中的對(duì)象的初婆,所以在訪問(wèn)一個(gè)對(duì)象時(shí),首先得到這個(gè)對(duì)象在堆內(nèi)存中地址猿棉,然后再按這個(gè)地址去獲得這個(gè)對(duì)象中的值磅叛,這就是傳說(shuō)中的引用訪問(wèn),而基本類型值時(shí)可以直接訪問(wèn)到的铺根。
如果按引用傳遞的話宪躯,是變量把它里面的值傳遞(復(fù)制)給了參數(shù),這個(gè)參數(shù)也指向了原對(duì)象位迂,如果在函數(shù)內(nèi)部把這個(gè)參數(shù)賦值另一個(gè)對(duì)象時(shí)访雪,這個(gè)參數(shù)就會(huì)更改它的值為新的內(nèi)存地址指向的新對(duì)象,此時(shí)原來(lái)的變量仍指向原來(lái)的對(duì)象掂林,這時(shí)他們相互獨(dú)立臣缀;但如果這個(gè)參數(shù)改變對(duì)象內(nèi)部的屬性的話,這個(gè)改變會(huì)體現(xiàn)在外部泻帮,因?yàn)樗麄児餐赶虻倪@個(gè)對(duì)象被修改了精置。這也就是上面所說(shuō)的按值傳遞和共享傳遞的區(qū)別。
2017,8.24 二次理解:
js中所有類型都是按值傳遞的(傳遞的是棧中的內(nèi)容)锣杂,因?yàn)槁暶髯兞繒r(shí)不同方式的內(nèi)存分配(基本類型 儲(chǔ)存在棧中脂倦;引用類型值 儲(chǔ)存在堆中,棧中儲(chǔ)存 引用地址)元莫。所以基本類型 按值傳遞的是 棧中的直接值赖阻,而引用類型 按值傳遞的是 棧中的 引用地址。
而共享傳遞的意思是:你外部一個(gè)對(duì)象傳到函數(shù)里做為一個(gè)參數(shù)踱蠢,這個(gè)參數(shù)是和原對(duì)象一樣火欧,是指向堆中值的 一個(gè)地址,你在函數(shù)的這個(gè)參數(shù)中修改參數(shù)的屬性是會(huì)影響到外部對(duì)象的,但你要是把這個(gè)參數(shù)再賦予一個(gè)新對(duì)象苇侵,這個(gè)參數(shù)在這個(gè)時(shí)候及之后都是 指向另一個(gè)堆中值的 一個(gè)地址赶盔,而這之前的這個(gè)參數(shù)(可能參數(shù)名字一樣)仍是指向 原堆中值的 一個(gè)地址。