成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

講清楚之 javascript 參數(shù)傳值

itvincent / 3446人閱讀

摘要:講清楚之參數(shù)傳值參數(shù)傳值是指函數(shù)調(diào)用時(shí),給函數(shù)傳遞配置或運(yùn)行參數(shù)的行為,包括通過進(jìn)行傳值。所以對(duì)的賦值會(huì)改變上下文棧中標(biāo)識(shí)符保存的具體值此時(shí)如果使用的是按引用傳遞,則變量所指向的對(duì)象因該也被賦值為。

講清楚之 javascript 參數(shù)傳值

參數(shù)傳值是指函數(shù)調(diào)用時(shí),給函數(shù)傳遞配置或運(yùn)行參數(shù)的行為,包括通過call、apply 進(jìn)行傳值。

在實(shí)際開發(fā)中,我們總結(jié)javascript參數(shù)傳值分為基本數(shù)據(jù)類型按值傳遞(String、Numbe、Boolean、Null、undefind),引用數(shù)據(jù)類型按引用傳遞(Object, 包括Array、Function、Data)。這篇文章將要糾正這一誤解: 實(shí)質(zhì)上引用類型是按共享傳遞的。

在探索傳值問題前,我們先看一下 javascript 在聲明變量時(shí)是怎樣分配內(nèi)存的

原始值:存儲(chǔ)在棧(stack)中的簡(jiǎn)單數(shù)據(jù)段,也就是說,它們的值直接存儲(chǔ)在變量訪問的位置。這是因?yàn)檫@些原始類型占據(jù)的空間是固定的,所以可將他們存儲(chǔ)在較小的內(nèi)存區(qū)域 – 棧中。這樣存儲(chǔ)便于迅速查尋變量的值。

引用值:存儲(chǔ)在堆(heap)中的對(duì)象,也就是說,存儲(chǔ)在變量處的值是一個(gè)指針(point),指向存儲(chǔ)對(duì)象的內(nèi)存地址。這是因?yàn)椋阂弥档拇笮?huì)改變,所以不能把它放在棧中,否則會(huì)降低變量查尋的速度。相反,放在變量的??臻g中的值是該對(duì)象存儲(chǔ)在堆中的地址。地址的大小是固定的,所以把它存儲(chǔ)在棧中對(duì)變量性能無任何負(fù)面影響。

基本類型是將原始值保存在棧中。引用類型是將數(shù)據(jù)保存在堆中,然后在棧中建立堆地址的引用。在javascript中是不允許直接訪問保存在堆內(nèi)存中的對(duì)象的,所以在訪問一個(gè)對(duì)象時(shí),首先得到的是這個(gè)對(duì)象在堆內(nèi)存中的地址,然后再按照這個(gè)地址去獲得這個(gè)對(duì)象中的值,這就是傳說中的按引用訪問。而原始類型的值則是可以直接訪問到的。不同的內(nèi)存分配機(jī)制也帶來了不同的訪問機(jī)制。

而基本類型和引用類型在變量復(fù)制的時(shí)候也存在區(qū)別:

原始值:在將一個(gè)保存著原始值的變量復(fù)制給另一個(gè)變量時(shí),會(huì)將原始值的副本賦值給新變量,此后這兩個(gè)變量是完全獨(dú)立的,他們只是擁有相同的 value 而已。

引用值:在將一個(gè)保存著對(duì)象內(nèi)存地址的變量復(fù)制給另一個(gè)變量時(shí),會(huì)把這個(gè)內(nèi)存地址賦值給新變量,也就是說這兩個(gè)變量都指向了堆內(nèi)存中的同一個(gè)對(duì)象,他們中任何一個(gè)作出的改變都會(huì)反映在另一個(gè)身上。復(fù)制是不會(huì)產(chǎn)生新的堆內(nèi)存消耗。

所以我們總結(jié) javascript 中所有函數(shù)參數(shù)都是按值傳遞,都是把形參復(fù)制給實(shí)參,只是基本數(shù)據(jù)類型復(fù)制的是原始值,而引用類型復(fù)制的是堆內(nèi)存的地址。

引用類型的這種求值策略就是 按共享傳遞(call by sharing).

理論知識(shí)梳理完了,下面舉幾個(gè)例子分析一下具體的情形.

基本數(shù)據(jù)類型傳值
let a = 1
function foo(x) {
    console.log(x)
}
foo(a)
console.log(a)
// 2
// 1

變量 a 的值直接復(fù)制到了foo函數(shù)的實(shí)參x上,此時(shí)變量x是變量 a 的一個(gè)副本。它們獨(dú)立的在各自的上下文棧中保存了值‘1’,且相互之間互不影響,我們對(duì) a、x的讀寫操作,操作的是他們各自的值。

示例圖中,在全局上下文和foo的上下文中各自保存了值1.

引用類型傳值
let a = {
    abc: 1
}
function foo(x) {
    x.abc = 2
    console.log(x.abc)
}
foo(a)
console.log(a.abc)
// 2
// 2

根據(jù)編碼經(jīng)驗(yàn)我們會(huì)很錯(cuò)誤的得出,上面的栗子是按引用傳遞。對(duì)象a的引用被傳遞到函數(shù)foo內(nèi)部, 函數(shù)內(nèi)部變量x指向全局變量a,從而實(shí)現(xiàn)了引用的傳遞,所以變量x和變量a讀寫的是同一個(gè)對(duì)象。我們用一張圖來揭示:

但其實(shí)是按共享傳遞。按引用傳遞是我們對(duì) javascript 求值策略的誤解,如果是按引用傳遞那下面這個(gè)例子就懵比了:

let a = {
    abc: 1
}
function foo(x) {
    console.log(x) // {abc: 1}
    x = 2
    console.log(x) // 2
}
foo(a)
console.log(a.abc) // 1

foo 函數(shù)執(zhí)行時(shí)第一個(gè)打印輸出 ‘{abc: 1}’, 第二個(gè)打印輸出 ‘2’, 調(diào)用 foo 函數(shù)后的console.log(a.abc)一句打印輸出‘1’。

按引用傳遞的話。表達(dá)式console.log(a.abc)是在 foo 函數(shù)執(zhí)行后執(zhí)行的,此時(shí)的a應(yīng)該已經(jīng)被賦值為 2, a.abc是不存在的應(yīng)該打印輸出 ‘undefind’。 但是卻打印輸出了 1,說明在 foo 函數(shù)的內(nèi)部執(zhí)行x = 2是并沒有修改外層對(duì)象 a 的值。

為什么會(huì)出現(xiàn)a、x在指向同一個(gè)對(duì)象后,對(duì)x賦值又沒有改變?cè)瓕?duì)象的值呢?

因?yàn)檫@里對(duì)象傳遞給實(shí)參是按共享傳遞(call by sharing)的,根據(jù)引用類型變量復(fù)制的特點(diǎn)(上面描述過):

foo 函數(shù)執(zhí)行時(shí), 形參 x 的值是傳進(jìn)去的對(duì)象 a 的內(nèi)存地址引用,即在變量對(duì)象創(chuàng)建階段x保存的是一個(gè)對(duì)象的堆內(nèi)存地址。此時(shí) a、x 都指向同一對(duì)象。 接著在函數(shù)的執(zhí)行階段,代碼的第二行將原始數(shù)據(jù)類型 2 賦值給 x,導(dǎo)致 x 不再保存原先的堆內(nèi)存地址轉(zhuǎn)而保存一個(gè)原始值,再次訪問 x 的時(shí)候是訪問對(duì) x 最后一次賦值的原始值。

所以對(duì) x 的賦值會(huì)改變上下文棧中標(biāo)識(shí)符 x 保存的具體值

此時(shí)如果使用的是按引用傳遞 ,則變量 a 所指向的對(duì)象因該也被賦值為 2。但其實(shí)對(duì) x 賦值為一個(gè)基本數(shù)據(jù)類型并沒有使原對(duì)象為一個(gè)字面量值,這就說明引用類型并不是按引用傳值,不是遵從按引用規(guī)則來處理值的寫入。

需要區(qū)分給對(duì)象屬性賦值與直接給對(duì)象賦值的區(qū)別:

let a = {
    abc: 1
}
function foo(x) {
    x.abc = 99
    console.log(x) // {abc: 99}
    x = 2
    console.log(x) // 2
}
foo(a)
console.log(a) // {abc: 99}

在 foo 函數(shù)內(nèi)部修改對(duì)象 x 的屬性,會(huì)導(dǎo)致 x、a 指向的對(duì)象被修改,因?yàn)樗鼈冎赶蛲粋€(gè)堆地址。

參考:

《javascript高級(jí)程序設(shè)計(jì)》

javascript傳遞參

JS是按值傳遞還是按引用傳遞?

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/107840.html

相關(guān)文章

  • 講清楚之 javascript 函數(shù)

    摘要:中函數(shù)是一等公民。小明小明調(diào)用函數(shù)時(shí),傳遞給函數(shù)的值被稱為函數(shù)的實(shí)參值傳遞,對(duì)應(yīng)位置的函數(shù)參數(shù)名叫作形參。所以不推薦使用構(gòu)造函數(shù)創(chuàng)建函數(shù)因?yàn)樗枰暮瘮?shù)體作為字符串可能會(huì)阻止一些引擎優(yōu)化也會(huì)引起瀏覽器資源回收等問題。 函數(shù) 之前幾節(jié)中圍繞著函數(shù)梳理了 this、原型鏈、作用域鏈、閉包等內(nèi)容,這一節(jié)梳理一下函數(shù)本身的一些特點(diǎn)。 javascript 中函數(shù)是一等公民。 并且函數(shù)也是對(duì)象,...

    Keagan 評(píng)論0 收藏0
  • 講清楚之執(zhí)行上下文

    摘要:棧底為全局上下文,棧頂為當(dāng)前正在執(zhí)行的上下文。位于棧頂?shù)纳舷挛膱?zhí)行完畢后會(huì)自動(dòng)出棧,依次向下直至所有上下文運(yùn)行完畢,最后瀏覽器關(guān)閉時(shí)全局上下文被銷毀。 講清楚之執(zhí)行上下文 標(biāo)簽 : javascript 什么是執(zhí)行上下文? 當(dāng) JavaScript 代碼執(zhí)行一段可執(zhí)行代碼時(shí),會(huì)創(chuàng)建對(duì)應(yīng)的上下文(execution context)并將該上下文壓入上下文棧(context stack...

    3fuyu 評(píng)論0 收藏0

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

0條評(píng)論

itvincent

|高級(jí)講師

TA的文章

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