javascript傳遞引數如果是object的話,是按值傳遞還是按引用傳遞?

時間 2021-05-30 22:28:49

1樓:王xx

函式在執行前首先要經歷預編譯的階段,預編譯會經歷四個階段:

1.建立乙個AO物件

2.找形參和變數宣告,將變數和形參名作為AO物件的屬性名,並且將值賦成undefined

3.將實參值和形參統一

4.在函式體裡面找出函式宣告,並且將值賦予函式體,(如果函式體的名字和前面的變數名或者形參名重複,那麼會覆蓋前面的屬性值)

這個例子裡面,函式執行前,setName()函式的AO(Activation Object)(執行期上下文)物件裡面會有乙個名字為"obj"的屬性名,並且這個值為person物件指向的位址。在函式執行的時候,就相當於person和obj指向同乙個位址,函式修改了obj這個變數儲存的位址的name屬性值,間接的修改了person物件name的屬性值,但是person仍然指向原來的位址,由於obj這個變數的作用域只在函式當中,函式繼續執行的時候,obj這個變數儲存的位址指向了乙個新的物件的位址,這個物件的作用域只是在函式區域性,和person沒有任何關係。隨著函式執行完畢,記憶體被釋放,obj這個變數也隨之消失。

所以person物件name的屬性值是第一次修改的「Nicholas".

建議題主看一下預編譯的相關知識。

2樓:Marq

世界萬物,皆有因果。事實上,大部分語言函式都是按照值傳遞,乙個被定義的初始變數,希望可以被複製,去改變複製之後的值,但不希望被改變本身。就像我發明了乙個東西,我可以讓你去生產,但是你不能把我的專利變成你的,否則世界就亂了。

這個時候對ES6進行深入理解,去了解letconst的真正意義吧!

3樓:

當物件作為引數傳遞到函式中時,乙個指向記憶體中該物件實際值的指標得到複製,再被傳遞到函式中去。

obj.

name

="Nicholas"

有效是因為,該變數obj指向的位置和person變數相同。

而obj

=new

Object

()改變了複製的指標的位置,故,

obj.

name

="Greg"

無法改變原來物件的內容, 因為此時obj變數已不再指向原位置。

4樓:liuyan

按值傳遞

2.按引用傳遞

例2:這是典型的按引用傳遞

這是大家所知道,所認為的按引用傳遞

但是其實並不是所謂的按引用傳遞

例3如果是按照引用傳遞值,那麼這裡的物件o應該為,但是這裡物件o在呼叫函式以後並沒有改變;

解釋如下:

首先引用型別並不是儲存物件本身,而是儲存了乙個引用,用來指向堆空間的物件;

當引用型別從乙個變數o1賦值給另外乙個變數o2,其實就是將o1這個引用複製了一次給o2,這樣,兩個變數o1,o2都有相同的引用指向堆空間的同乙個物件,所以會引起彼此的改變,這就是大家所說的按照引用傳遞;

但是當給o1,o2中任意乙個賦值,(假設給o2賦值,如下圖,給o2賦值了乙個物件),其實就是改變了o2的引用,也就是改變了o2所指的物件,此時o2並不是繼續指向o1所指的物件,而是其他的;此時o1,o2對彼此就沒有影響,因為它們並沒有指向同乙個物件了,這就是例3的解釋。

綜合上述,所以還是按值傳遞,對於引用型別傳遞的引用是值 !! 是值!! 是值!!是符合Nicholas書中所講的。

5樓:tigerx

引數傳遞其實都是值傳遞,引用型別引數傳入之後相當於在區域性建立了乙個區域性變數同時這個區域性變數與外部變數是引用同一位址,所以區域性變數重新賦值,在外部變數也體現出來了。

6樓:Rlynn

最近看演算法,又繞回這個問題,現在仔細想想,為什麼覺得傳值或是傳引用這個說法怪怪的,或者又是說不太準確。

在方法裡面的引數變數,其實相當於乙個新的變數,只是被賦予了值或者是位址,

類似於var name = "a";

setName(name);

function setName(newname)如果按順序執行,函式裡面執行效果就相當於

var newname = name;

newname = "b";

同樣的道理,如果是

var obj =

function setName(newname)就相當於

var newname = obj;

newname .name = "b";

newname = new Object();

newname.name="c";

所以才會導致 obj的屬性結果發生改變

當初看紅寶書,傳值這個說法讓我覺得好難理解,或許過於複雜化了,現在想想可能會有更好的表達。

7樓:

(define x(

list 12

3))(define (f

x)(begin

(set-car! x3

)(set! x(

list 56

7))x))

(fx)

;; return '(5 6 7) while x is now '(3 2 3)

8樓:貘吃饃香

湊熱鬧,隨便寫寫。

按引用傳遞和變數是個引用型別,貌似被混淆了。

js 是沒法按引用傳遞的,只有變數是引用型別。

要搞清楚得用兩者都有的語言來搞下,正好 php 都有它還是指令碼,然後搞了下。

例子裡就是為了能有 & 來作引用傳遞。

<?

phpclass

Bar$a

=new

Foo();

$a->x=

10;function

foo(&$n

)foo($a

);print_r($a

);這裡是引用傳遞 $a 並修改

結果為:

Bar Object ( [x] => 3100 ) Bar Object ( [x] => 3100 )

修改下,去掉 & 這個引用傳遞符號

<?

phpclass

Bar$a

=new

Bar();

$a->x=

10;function

foo($n)

foo(

$a);

print_r($a

);此時 $a 是按其自身的引用值型別傳遞。

結果為:

Bar Object ( [x] => 3100 ) Bar Object ( [x] => 200 )

所以,js 本身就沒有按引用傳遞的情況下。

函式引數是按照是否為引用值型別來決定如何處理。

實際上看出,函式內變數值為 copy 引用值型別的指標位址存放在棧內來處理。如同

@蘇墨橘 妹紙表述的。

ps:開了一天會……尼瑪就寫了這麼多,懶得繼續,摺疊吧……

9樓:

很簡單,都是值傳遞。(都是棧內資料的拷貝)但是,要分辨 實參的值代表什麼?

這就牽扯到JS資料型別問題: 簡單資料型別和複雜資料型別簡單資料型別包括: Undefined、Null、Boolean、Number和String

複雜資料型別就是: Object

所以:簡單資料型別傳的是值本身 (因為直接把值存在棧內)複雜資料型別傳的是物件在記憶體裡面的位址 (因為複雜物件存在堆內,所以在棧裡存物件所在的堆位址)

這一點 @蘇墨橘 講解的很細緻了。

其實:把函式 setName 翻譯一下:

function

setName

(arguments

)更好理解。

相信你已經明白了。

10樓:

Primitive type (string, number, etc.) are passed by value and objects are passed by reference. If you change a property of the passed object, the change will be affected.

However, you assign a new object to the passed object, the changes will not be reflected.

e.g.

var num = 100,

name = "AAA",

obj1value: "aaa"obj2value: "bbb"obj3 = obj2;

function change(num, name, obj1, obj2)

change(num, name, obj1, obj2);

console.log(num); // 10

console.log(name); // "AAA"

console.log(obj1.value); //"aaa"

console.log(obj2.value); //"ccc"

console.log(obj3.value); //"ccc"

以上是本人自己的看法, 希望有幫助. (本人在國外才開始所前端的東西,好多名字不知道確切中文的翻譯是什麼,望諒解...)

11樓:Saviio

書上雖然是寫的沒錯,但是由於ECMAScript的所謂的「傳值」稍有些特殊,它求值策略可以概括成call by value where value is the reference copy

在書裡舉的這個例子裡,它傳遞的的確是引用,但實際上他應用的策略卻是 call by sharing,通俗的說就是,它並不是把引用直接傳遞進去,而是把引用的拷貝傳遞進去儲存在函式內部的AO物件裡。

因此,如果你對這個引用進行第二次賦值的時候,實際上把這份引用指向了另外乙個物件,所以之後對這個物件的操作不會影響到外部的物件。

vara=,

b=function

change

(obj

,ischange

)return;}

obj.x=

"X"obj.y

="Y"

}change(a

)//x:"X",y:"Y"

change(b

,true

)//x:1,y:2

之前 @楊志 的回答中有提到過這部分內容:關於 Js 迴圈新增事件時閉包的影響有哪些解法? - 楊志的回答,若還想深入,只能閱讀ECMAScript規範了。

JavaScript中函式都是值傳遞嗎?

Marq 世界萬物,皆有因果。事實上,大部分語言函式都是按照值傳遞,乙個被定義的初始變數,希望可以被複製,去改變複製之後的值,但不希望被改變本身。就像我發明了乙個東西,我可以讓你去生產,但是你不能把我的專利變成你的,否則世界就亂了。這個時候對ES6進行深入理解,去了解let,const的真正意義吧!...

JavaScript為什麼不實現捨去引數的用法?

navegador 折衷的土辦法 const e undefined在鍵盤上比 更靠近左手 鍵盤上 附近的字母只有e 和 r epsilon 形狀和 e 相近function tst a 400,b 20,c tst e e 555 400 20 555 tst 123,e 555 123 20 5...

彙編中引數如何用堆疊傳遞?

方彥 這取決於你要編寫的架構,和你打算遵守的呼叫約定。例如假如你希望在X86平台上遵守cdecl,即呼叫者從最右邊的引數開始,依次將引數壓棧,在被調方執行完畢後,將返回值寫入EAX,然後返回,由呼叫者將引數彈出,實現棧的平衡。假如你希望用stdcall,這是X86上Windows API的預設呼叫方...