摘要:寫在最前本次嘗試通過流程圖的形式并結合兩個例子來重新理解一下中的參數(shù)傳遞。歡迎關注我的博客,不定期更新中參數(shù)到底如何傳遞借用紅寶書的一句話中所有函數(shù)的參數(shù)都是按值傳遞的這個值如果是簡單類型,那么就是其本身。同時執(zhí)行第一個結果即為。
寫在最前
本次嘗試通過流程圖的形式并結合兩個例子來重新理解一下JavaScript中的參數(shù)傳遞。
歡迎關注我的博客,不定期更新中——
參數(shù)到底如何傳遞?借用紅寶書的一句話:
ECMAScript中所有函數(shù)的參數(shù)都是按值傳遞的
這個值如果是簡單類型,那么就是其本身。如果是引用類型也就是對象傳遞的就是指向這個對象的地址。故我們可以認為參數(shù)傳遞全部都是值傳遞,那么具體怎么理解呢?看下例子:
第一個例子var obj = { n: 1 }; function foo(data) { data = 2; console.log(data); //2 } foo(obj); console.log(obj.n) // 1
先不說為什么原因,我們就通過畫圖的方式來走一遍流程,我相信應該就能理解其中的參數(shù)傳遞了。切記傳遞引用類型傳遞的是指針!
首先執(zhí)行var obj = {n: 1}; ,可以看作在棧的001地址中存入了一個指向{n:1}的指針*p
接下來為聲明function foo 此時會創(chuàng)建函數(shù)執(zhí)行上下文,產(chǎn)生一個變量對象,其中聲明了形參data,由于函數(shù)沒有執(zhí)行,當前值為undefined。我們記data地址為022。關于更多變量對象的知識可以參考冴羽老師的這篇JavaScript深入之變量對象,本文不深入研究關于AO相關,你只需要知道在聲明這個函數(shù)的時候里面的形參已經(jīng)被創(chuàng)建出來了。
執(zhí)行foo(obj) 其中會進行參數(shù)傳遞,其中將obj中存儲的*p拷貝給處在022地址的data,那么此時它們就指向了同一個對象,如果某一個變量更改了n的值,另一個變量中n的值也會更改,因為其中保存的是指針。
進入函數(shù)內(nèi)部,順序執(zhí)行data = 2;此時002地址存儲了基本類型值,則直接存儲在棧中,從而與堆中的{n:1}失去了聯(lián)系。從而打印console.log(data) // 2 ,最后發(fā)現(xiàn)初始開辟的{n:1}對象沒有過更改,故而 console.log(obj.n) // 1仍然打印1。
第二個例子var obj = {n:1}; (function(obj){ console.log(obj.n); //1 obj.n=3; var obj = {n:2}; console.log(obj.n) //2 })(obj); console.log(obj.n) //3
整體來看這個例子中出現(xiàn)了同名覆蓋的問題。不太了解代碼如何執(zhí)行的流程,可能會因為同名的關系而有些混亂,不過沒關系。只要按照上一個例子的流程圖中的執(zhí)行過程,一定可以得出正確的結果。
聲明變量obj,地址為011其中存入指向{n:1}的指針*p
聲明函數(shù),雖然同為obj變量名,但是形參obj為AO中的屬性,不會與全局造成覆蓋,其擁有新的地址記作022,在未執(zhí)行前其值為undefined。
函數(shù)立即執(zhí)行,此時將全局obj賦值給形參obj,我們忽略這個重復命名的問題,其實就是將011中的 指針*p拷貝了一份給了022。同時執(zhí)行第一個console.log(obj.n)結果即為1。
執(zhí)行obj.n=3,此時為函數(shù)的形參即022中的obj來改變了對象內(nèi)n的值。
最關鍵的一步:var obj = {n:2}; 由于對象命名的關系可能很多童鞋就會有點懵,但依然按照同樣的方式來分析即可,由于使用了var那么就是新聲明一個對象,從而會在棧中壓入新的地址記作033,其中存入了新的指針指向了新的對象{n:2}。從而之后打印的console.log(obj.n)結果則應是新開辟的對象中的n的值。
最后打印 console.log(obj.n) //3很顯然,全局的對象有過一次更改其值為3。
小結至此我們走完了上述兩段代碼涉及變量的所有“心路歷程”,由于作者不是科班出身,這個圖中對于堆棧以及變量重名的描述可能不是非常的準確,有差錯的地方還望不吝賜教~重點是能理解我希望表達的意思就好??偟膩碚f關鍵點就在于傳參的過程中存在一次值的拷貝,同時如果賦值對象是引用類型傳入的是指針,明白這兩點之后再加上之前流程圖的分析相信再遇到類似的問題都可以有較為一致的思路了。
最后慣例po作者的博客,不定時更新中——
有問題歡迎在issues下交流。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/90603.html
摘要:繼承和前面兩篇文章中的知識非常相關,如果對函數(shù)創(chuàng)建原理和原型鏈不熟悉,請猛戳高級程序設計筆記創(chuàng)建對象高級程序設計筆記原型圖解繼承,通俗的說,就是將自身不存在的屬性或方法,通過某種方式為自己所用文章分別介紹原型鏈繼承繼承借用構造函數(shù)繼承組合繼 繼承和前面兩篇文章中的知識非常相關,如果對函數(shù)創(chuàng)建原理和原型鏈不熟悉,請猛戳:《javascript高級程序設計》筆記:創(chuàng)建對象《javascri...
摘要:因此,所有在方法中定義的變量都是放在棧內(nèi)存中的當我們在程序中創(chuàng)建一個對象時,這個對象將被保存到運行時數(shù)據(jù)區(qū)中,以便反復利用因為對象的創(chuàng)建成本通常較大,這個運行時數(shù)據(jù)區(qū)就是堆內(nèi)存。 上一篇:《javascript高級程序設計》筆記:繼承近幾篇博客都會圍繞著圖中的知識點展開 showImg(https://segmentfault.com/img/bVY0C4?w=1330&h=618);...
摘要:一棧數(shù)據(jù)結構與不同,中并沒有嚴格意義上區(qū)分棧內(nèi)存與堆內(nèi)存。引用數(shù)據(jù)類型的值是保存在堆內(nèi)存中的對象。不允許直接訪問堆內(nèi)存中的位置,因此我們不能直接操作對象的堆內(nèi)存空間。為了更好的搞懂變量對象與堆內(nèi)存,我們可以結合以下例子與圖解進行理解。 showImg(https://segmentfault.com/img/remote/1460000009784102?w=1240&h=683); ...
摘要:并且如果使用那么必須要指明值使用簡單的數(shù)據(jù)類型不好使使用接口代理模式的注解也可以 屬于MyBatis的核心之一,這里面的坑比較多,大家多多看看吧 一 模糊查詢的三種方式介紹 我會使用resultMap處理結果集數(shù)據(jù) 1.死數(shù)據(jù)的模糊查詢 映射文件 SELECT * FROM...
摘要:緩存緩存主要是通過請求和響應報文頭中的對應信息,來控制緩存的策略。就會返回一個的狀態(tài)碼,表示可以繼續(xù)使用客戶端本地緩存的數(shù)據(jù),并刷新超時時間。與之相對的,則表示當前響應是針對單個用戶的,并非通用數(shù)據(jù),因此不建議任何中間緩存對其進行緩存。 showImg(https://segmentfault.com/img/remote/1460000015383634?w=1080&h=720);...
閱讀 1917·2021-11-24 11:16
閱讀 3265·2021-09-10 10:51
閱讀 3216·2021-08-03 14:03
閱讀 1272·2019-08-29 17:03
閱讀 3253·2019-08-29 12:36
閱讀 2239·2019-08-26 14:06
閱讀 502·2019-08-23 16:32
閱讀 2695·2019-08-23 13:42