摘要:中參數傳遞為什么必定是按值傳遞,有些疑惑,以下是一些理解。指兩個變量是兩個獨立的變量,唯獨在于他們各自的對象都是在同一個堆內存空間的。就是實際上沒有把堆內存中的對象作為函數參數。
js中參數傳遞為什么必定是按值傳遞,有些疑惑,以下是一些理解。
js高級程序設計(第三版)的第四章,表明了基本數據類型(Undefined、Null、Boolean、Number、String)是按值訪問的,對象是按引用訪問的。
首先,看下引用類型變量是怎樣的(obj1、obj2都是對象類型):
var obj1 = new Object(); var obj2 = obj1;
簡單來說,obj1、obj2都是變量,他們分別有一個指針,各自指向各自的棧內存,然后棧內存中存放有堆內存地址和一些別的數據,那么就又有第二個指針根據棧內存中存放的地址指向堆內存,堆內存中存放的是同一個的對象(因為obj1和obj2棧內存中的地址是相同的)。
注意到書中原話:
當從一個變量向另一個變量復制引用類型的值時,同樣也會將存儲在變量對象中的值復制一份放到為新變量分配的空間中。不同的是,這個值的副本實際上是一個指針,而這個指針指向存儲在堆中的一個對象。復制操作結束后,兩個變量實際上將引用同一個對象。因此,改變其中一個變量,就會影響另一個變量。
然后,實驗代碼如下:
var t1 = new Object(); var t2 = t1; t2.name ="t1"; t2 = new Object(); //本質為t2的指針指向了一個新空間 console.log(t1.name); //輸出t1 console.log(t2.name); //輸出undefined
分析:
var t2 = t1;
這行代碼實質是把t1棧內存中的數據復制在t2的棧內存中,棧內存中存放的堆內存地址就是一樣的,因而指向了同一個堆內存地址,即指向同一個對象。
t2 = new Object();
這行代碼就是把t2在棧內存中存放的地址改變了,變成了一個此刻不在使用的地址,然后t2的指針指向了這個新地址,所以之后t1和t2無關了。
可以看出,書中寫的 復制操作結束后,兩個變量實際上將引用同一個對象。 指兩個變量是兩個獨立的變量,唯獨在于他們各自的對象都是在同一個堆內存空間的。我通俗理解為:t1和t2兩個變量本身是按值訪問的,t1和t2指向的對象是按引用訪問的,但實際上定義變量,自然是為了操作變量指向的對象。
下面是對于函數參數傳遞中的一些理解:
先看一下,讓人誤以為參數是引用傳遞的代碼:
var t1 = new Object(); function change(obj){ obj.name = "lalala"; } change(t1); console.log(t1.name); //輸出了lalala
結果是外部的t1多了一個屬性name,原因就在于確實是參數傳遞,把t1按值傳遞給了obj,操作他們各自屬性的時候,屬性仍然是按引用傳遞的,我們傳的參數又不是t1的屬性。
強調一下,我上面說t1的屬性,是不正確的說法,嚴格來說,不是t1多了一個屬性,也不是t1的屬性,而是t1指向的對象多了一個屬性,或者說那是t1指向的對象的屬性,t1只是一個變量罷了。
再看下面代碼:
var t1 = new Object(); function change(obj){ obj.name = "t1"; obj = new Object(); obj.name = "new t1"; } change(t1); console.log(t1.name); //輸出t1
輸出結果,t1.name仍然是‘‘t1’’,再進行obj = new Object()時候,因為棧內存中數據的改變,這里的obj最終指向的對象不是t1指向的對象了,就函數內部再也操作不到t1一開始指向的對象了,類似于下面代碼中t2的重新聲明。
var t1 = new Object(); var t2 = t1; t2.name ="t1"; t2 = new Object(); console.log(t1.name); //輸出t1 console.log(t2.name); //輸出undefined
結論:函數的參數傳遞是按值傳遞的,但對于參數是引用類型變量,該變量指向的對象的屬性(就是t1.name之類的)是按引用訪問的,因此改變對象的屬性會反映在外部對象上;但變量本身按值傳遞了,因此改變內部變量(就只改變t1、t2),外部變量不會有改變。就是實際上沒有把堆內存中的對象作為函數參數。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93204.html
摘要:學習中函數參數值傳遞和引用傳遞的學習中函數參數值傳遞和引用傳遞在紅寶書中說到,中所有函數的參數都是按值傳遞的。 學習JS中函數參數值傳遞和引用傳遞的學習 JS中函數參數值傳遞和引用傳遞 在JavaScript紅寶書中說到,ECMAScript中所有函數的參數都是按值傳遞的。理解這個概念先要從JS的堆內存和棧內存說起:棧內存為自動分配的內存空間,它由系統自動釋放;堆內存則是動態分配的內存...
摘要:設計模式是以面向對象編程為基礎的,的面向對象編程和傳統的的面向對象編程有些差別,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續了解設計模式必須要先搞懂面向對象編程,否則只會讓你自己更痛苦。 JavaScript 中的構造函數 學習總結。知識只有分享才有存在的意義。 是時候替換你的 for 循環大法了~ 《小分享》JavaScript中數組的那些迭代方法~ ...
摘要:接著下一個例子賦予副本新的地址可見,函數參數傳遞的并不是變量的引用,而是變量拷貝的副本,當變量是原始類型時,這個副本就是值本身,當變量是引用類型是,這個副本是指向堆內存的地址。 轉載自ConardLi: 《【JS進階】 你真的掌握變量和類型了嗎》 公眾號: code秘密花園 1. JavaScript數據類型 ECMAScript標準規定了7種數據類型,這些數據類型分為原始類型和對象...
這幾天遇到js參數傳遞方式的問題,深切探究一番,將所得結果總結于此 常見的幾種傳遞方式 傳值調用(call by value) 在傳值調用中實際參數被求值,其值被綁定到函數中對應的變量上(通常是把值復制到新內存區域)。在函數返回后調用者作用域里的曾傳給函數的任何東西都不會變。 傳引用調用(call by reference) 在傳引用調用求值中,傳遞給函數的是它的實際參數的隱式引用(即實際參數的地...
摘要:值類型基本類型和棧內存值類型也稱為原始數據或原始值這類值存儲在棧內存中基本類型的值不可以修改。目前中的基本類型一共有六種。堆的使用規則當創建數組時,就會在堆內存中創建一個數組對象,并且在棧內存中創建一個對數組的引用。 值類型(基本類型)和棧內存 值類型也稱為原始數據或原始值(primitive value).這類值存儲在棧(stack)內存中, 基本類型的值不可以修改。每當我們定義一個...
閱讀 685·2021-11-25 09:43
閱讀 2953·2021-11-24 10:20
閱讀 1002·2021-10-27 14:18
閱讀 1076·2021-09-08 09:36
閱讀 3382·2021-07-29 14:49
閱讀 1784·2019-08-30 14:07
閱讀 2937·2019-08-29 16:52
閱讀 3049·2019-08-29 13:12