成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript 是傳值調(diào)用還是傳引用調(diào)用?

darkbug / 2533人閱讀

摘要:所以傳遞給函數(shù)的值是這個(gè)值,所以函數(shù)執(zhí)行結(jié)束原始變量并不會(huì)改變。傳值調(diào)用在傳值調(diào)用中,傳遞給函數(shù)參數(shù)是函數(shù)被調(diào)用時(shí)所傳實(shí)參的拷貝。引用類(lèi)型變量的值是一個(gè)指針,指向堆內(nèi)存中的實(shí)際對(duì)象。所以傳共享調(diào)用也可以說(shuō)是傳值調(diào)用。

1. 例子

先來(lái)看兩個(gè)個(gè)來(lái)自于 《JavaScript 高級(jí)程序設(shè)計(jì)》P70-P71 的兩個(gè)例子。

1.1. 基本類(lèi)型參數(shù)傳遞
function addTen(num) {
  num += 10;
  return num;
}

var count = 20;
var result = addTen(count);
alert(count); // 20, 沒(méi)有變化
alert(result); // 30

書(shū)上解釋說(shuō),JavaScript 參數(shù)傳遞都是按值傳參。

所以傳遞給 addTen 函數(shù)的值是 20 這個(gè)值,所以函數(shù)執(zhí)行結(jié)束原始變量 count 并不會(huì)改變。

1.2. 引用類(lèi)型參數(shù)傳遞
function setName(obj) {
  obj.name = "Nicholas";
  obj = new Object();
  obj.name = "Greg";
}

var person = new Object();
setName(person);
alert(person.name); // Nicholas

為什么結(jié)果是 Nicholas 呢?

疑問(wèn):如果是傳值,那應(yīng)該是把 person 變量的值(也就是一個(gè)指向堆內(nèi)存中對(duì)象的指針)傳遞到函數(shù)中,obj.name = "Greg"; 改變了堆內(nèi)存中對(duì)象的屬性,為什么 person.name 還是 Nicholas

2. 傳值還是傳引用?

讓我們?cè)賹⑸厦鎯蓚€(gè)例子綜合為下面的例子:

function changeStuff(a, b, c) {
  a = a * 10;
  b.item = "changed";
  c = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

changeStuff(num, obj1, obj2);

console.log(num);
console.log(obj1.item);    
console.log(obj2.item);

最終的輸出結(jié)果是:

10
changed
unchanged

所以 JS 到底是傳值調(diào)用還是傳引用調(diào)用呢?要弄清楚這個(gè)問(wèn)題,首先我們要明白到底什么是傳值調(diào)用(Call-ny-value)傳引用調(diào)用(Call-by-reference)。

2.1. 傳值調(diào)用(Pass by value)

在傳值調(diào)用中,傳遞給函數(shù)參數(shù)是函數(shù)被調(diào)用時(shí)所傳實(shí)參的拷貝。在傳值調(diào)用中實(shí)際參數(shù)被求值,其值被綁定到函數(shù)中對(duì)應(yīng)的變量上(通常是把值復(fù)制到新內(nèi)存區(qū)域)。

changeStuff 的參數(shù) a b cnum1 obj1 obj2 的拷貝。所以無(wú)論 a b c 怎么變化,num1 obj1 obj2 都保持不變。

問(wèn)題就在于 obj1 變了。

2.2. 傳引用調(diào)用(Pass by reference)

在傳引用調(diào)用調(diào)用中,傳遞給函數(shù)的是它的實(shí)際參數(shù)的隱式引用而不是實(shí)參的拷貝。通常函數(shù)能夠修改這些參數(shù)(比如賦值),而且改變對(duì)于調(diào)用者是可見(jiàn)的。

也就是說(shuō) changeStuff 函數(shù)內(nèi)的 a b c 都分別與 num obj1 obj2 指向同一塊內(nèi)存,但不是其拷貝。函數(shù)內(nèi)對(duì) a b c 所做的任何修改,都將反映到 num obj1 obj2 上 。

問(wèn)題就在于 numobj2 沒(méi)變。

從上面的代碼可以看出,JavaScript 中函數(shù)參數(shù)的傳遞方式既不是傳值,也不是傳引用。主要問(wèn)題出在 JS 的引用類(lèi)型上面。

JS 引用類(lèi)型變量的值是一個(gè)指針,指向堆內(nèi)存中的實(shí)際對(duì)象。

2.3. 傳共享調(diào)用(Call by sharing)

還有一種求值策略叫做傳共享調(diào)用(Call-by-sharing/Call by object/Call by object-sharing)。

傳共享調(diào)用和傳引用調(diào)用的不同之處是,該求值策略傳遞給函數(shù)的參數(shù)是對(duì)象的引用的拷貝,即對(duì)象變量指針的拷貝。

也就是說(shuō), a b c 三個(gè)變量的值是 num obj1 obj2 的指針的拷貝。 a b c 的值分別與 num obj1 obj2 的值指向同一個(gè)對(duì)象。函數(shù)內(nèi)部可以對(duì) a b c 進(jìn)行修改可重新賦值。

function changeStuff(a, b, c) {
  a = a * 10; // 對(duì) a 賦值,修改 a 的指向,新的值是 a * 10
  b.item = "changed"; // 因?yàn)?b 與 obj1 指向同一個(gè)對(duì)象,所以這里會(huì)修改原始對(duì)象 obj1.item 的內(nèi)容
  c = {item: "changed"}; // 對(duì) c 重新賦值,修改 c 的指向,其指向的對(duì)象內(nèi)容是 {item: "changed"}
}
3 代碼分析

接下來(lái)讓我們?cè)賮?lái)分析一下代碼。

3.1 變量初始化
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

3.2 調(diào)用函數(shù)
changeStuff(num, obj1, obj2);

可以看到,變量 a 的值就是 num 值的拷貝,變量 b c 分別是 obj1 obj2 的指針的拷貝。

函數(shù)的參數(shù)其實(shí)就是函數(shù)作用域內(nèi)部的變量,函數(shù)執(zhí)行完之后就會(huì)銷(xiāo)毀。

3.3 執(zhí)行函數(shù)體
a = a * 10;
b.item = "changed";
c = {item: "changed"};

如圖所示,變量 a 的值的改變,并不會(huì)影響變量 num

b 因?yàn)楹?obj1 是指向同一個(gè)對(duì)象,所以使用 b.item = "changed"; 修改對(duì)象的值,會(huì)造成 obj1 的值也隨之改變。

由于是對(duì) c 重新賦值了,所以修改 c 的對(duì)象的值,并不會(huì)影響到 obj2。

4. 結(jié)論

從上面的例子可以看出,對(duì)于 JS 來(lái)說(shuō):

基本類(lèi)型是傳值調(diào)用

引用類(lèi)型傳共享調(diào)用

傳值調(diào)用本質(zhì)上傳遞的是變量的值的拷貝。

傳共享調(diào)用本質(zhì)上是傳遞對(duì)象的指針的拷貝,其指針也是變量的值。所以傳共享調(diào)用也可以說(shuō)是傳值調(diào)用。

所以《JavaScript 高級(jí)程序設(shè)計(jì)》說(shuō) JavaScript 參數(shù)傳遞都是按值傳參 也是有道理的。

本文同步于我的博客 https://github.com/nodejh/nodejh.github.io/issues/32

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81601.html

相關(guān)文章

  • Java

    摘要:傳值和傳址有什么區(qū)別是傳值還是傳址開(kāi)始在傳參時(shí),是傳值還是傳址傳值和傳址假設(shè)要將傳到。傳值和傳址是傳值是傳值。分別是基本類(lèi)型,對(duì)象和數(shù)組,還有。常量池時(shí),好比是一張紙條,當(dāng)要傳值給時(shí),事實(shí)是把紙條上的內(nèi)容抄給了。 傳值和傳址有什么區(qū)別?Java是傳值還是傳址? 開(kāi)始 Java在傳參時(shí),是傳值還是傳址? 傳值和傳址 假設(shè)要將A傳到B。如果是傳值,就意味著將A中存放的值復(fù)制一份給B,B存的...

    fnngj 評(píng)論0 收藏0
  • 講清楚之 javascript 參數(shù)

    摘要:講清楚之參數(shù)傳值參數(shù)傳值是指函數(shù)調(diào)用時(shí),給函數(shù)傳遞配置或運(yùn)行參數(shù)的行為,包括通過(guò)進(jìn)行傳值。所以對(duì)的賦值會(huì)改變上下文棧中標(biāo)識(shí)符保存的具體值此時(shí)如果使用的是按引用傳遞,則變量所指向的對(duì)象因該也被賦值為。 講清楚之 javascript 參數(shù)傳值 參數(shù)傳值是指函數(shù)調(diào)用時(shí),給函數(shù)傳遞配置或運(yùn)行參數(shù)的行為,包括通過(guò)call、apply 進(jìn)行傳值。 在實(shí)際開(kāi)發(fā)中,我們總結(jié)javascript參數(shù)傳...

    itvincent 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<