今天在看 seajs-2.2.1/src/util-events.js源碼,裏面有段代碼不是很理解:javascript
var events = data.events = {} // Bind event seajs.on = function(name, callback) { var list = events[name] || (events[name] = []) list.push(callback) return seajs }
局部變量 list的值的修改,居然會影響到全局變量 events[name],因而猜測到 JavaScript裏面應該有引用傳遞一說!趕忙查了下網絡資料,惡補基礎知識,彙總以下:php
文章一:JavaScript傳遞變量:值傳遞?引用傳遞?java
當變量A賦值給變量B時,會將棧中的值複製一份到爲新變量分配的空間中。 網絡
如何理解?函數
var x = y = 1; y = 2; alert(x); // 輸出 1
x的值爲多少?性能
var obj = {}; var sub = {}; sub['id'] = 3; obj['sub'] = sub; sub['id'] = 4; alert(obj['sub']['id']); // 輸出4
obj['sub']['id']的值又爲多少?他們真的符合你的預期嗎?lua
咱們分別運行2段代碼,發現第1段程序中x的值沒有改變,而第2段程序中的obj['sub']['id']的值卻改變了。一樣是一個賦值操做,一樣是修改另一份拷貝的值,爲何一段程序源變量沒變,一段程序源變量變化了呢?這個傳遞究竟是按值傳遞仍是按引用傳遞的呢?spa
李鬆峯翻譯的《JavaScript 高級程序設計 第二版》中給出了答案。翻譯
在開始的這2個例子中,事實上都複製了A的值給B,不一樣的是,在第一個例子中,A的值是int型的1,而在第二個例子中,A的值是一個地址指針,這個地址指針能夠訪問到一個對象,複製以後,第1個例子中的B的值變成了新的int, 他的值爲1,而第2個例子中B的值變成了新的地址指針,他的值爲這個對象的地址。設計
下面的例子能夠幫助理解
function setName(obj){ obj.name = "test1"; obj = {}; obj.name = "test2"; } var person = new Object(); setName(person); alert(person.name); // 輸出 test1
能夠看到的是,儘管調用了setName函數修改了變量的name屬性,可是person.name的值並無改變。這是由於在函數中,obj指向的地址被改變了,所以修改這個地址的name屬性,並不會對原地址的name屬性形成影響。從另外一個方面,也印證了JavaScript的傳遞是按值傳遞。
文章二:JavaScript中 值的訪問 與 參數傳遞 的問題
數據類型
在 JavaScript 中數據類型能夠分爲兩類:
聲明變量時不一樣的內存分配
不一樣的內存分配機制也帶來了不一樣的訪問機制
在JavasSript中是不容許直接訪問保存在堆內存中的對象的,因此在訪問一個對象時,首先獲得的是這個對象在堆內存中的地址,而後再按照這個地址去得到這個對象中的值,這就是傳說中的按引用訪問。而原始類型的值則是能夠直接訪問到的。
複製變量時的不一樣
參數傳遞的不一樣
首先咱們應該明確一點:ECMAScript中全部函數的參數都是按值來傳遞的。可是爲何涉及到原始類型與引用類型的值時仍然有區別呢,還不就是由於內存分配時的差異。 (我對比了一下,這裏和複製變量時遵循的機制徹底同樣的,你能夠簡單地理解爲傳遞參數的時候,就是把實參複製給形參的過程)
因此,若是是按引用傳遞的話,是把第二格中的內容(也就是變量自己)整個傳遞進去(就不會有第四格的存在了)。但事實是變量把它裏面的值傳遞(複製)給了參數,讓這個參數也指向原對象。所以若是在函數內部給這個參數賦值另外一個對象時,這個參數就會更改它的值爲新對象的內存地址指向新的對象,但此時原來的變量仍然指向原來的對象,這時候他們是相互獨立的;但若是這個參數是改變對象內部的屬性的話,這個改變會體如今外部,由於他們共同指向的這個對象被修改了!來看下面這個例子吧:(傳說中的call by sharing)
var obj1 = { value:'111' }; var obj2 = { value:'222' }; function changeStuff(obj){ obj.value = '333'; obj = obj2; return obj.value; } var foo = changeStuff(obj1); console.log(foo);// '222' 參數obj指向了新的對象obj2 console.log(obj1.value); /* '333' obj1仍然指向原來的對象,之因此value改變了, *是由於changeStuff裏的第一條語句,這個時候obj是指向obj1的 . *再囉嗦一句,若是是按引用傳遞的話,這個時候obj1.value應該是等於'222'的 */
好了,以上就是關於這個問題的所有解釋了。
各位有興趣的話能夠去了解一下call by value ,call by reference call by sharing 等函數傳遞的機制call by sharing
還有stackoverflow上對於函數傳遞的這個問題解釋得至關精闢,值得一看。(下面有連接)
參考:
文章三:(知乎網討論)JavaScript傳遞參數若是是Object的話,是按值傳遞仍是按引用傳遞?