摘要:它對數(shù)組和對象使用按值傳遞,但這是在的共享傳參或拷貝的引用中使用的按值傳參。例如在這里,變量和值在執(zhí)行期間存儲在堆棧中。返回值這是可選的,函數(shù)可以返回值,也可以不返回值。變量被推入堆棧,從而在執(zhí)行時(shí)成為的副本。
這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第 22 篇。
想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你!
如果你錯(cuò)過了前面的章節(jié),可以在這里找到它們:
JavaScript 是如何工作的:引擎,運(yùn)行時(shí)和調(diào)用堆棧的概述!
JavaScript 是如何工作的:深入V8引擎&編寫優(yōu)化代碼的5個(gè)技巧!
JavaScript 是如何工作的:內(nèi)存管理+如何處理4個(gè)常見的內(nèi)存泄漏!
JavaScript 是如何工作的:事件循環(huán)和異步編程的崛起+ 5種使用 async/await 更好地編碼方式!
JavaScript 是如何工作的:深入探索 websocket 和HTTP/2與SSE +如何選擇正確的路徑!
JavaScript 是如何工作的:與 WebAssembly比較 及其使用場景!
JavaScript 是如何工作的:Web Workers的構(gòu)建塊+ 5個(gè)使用他們的場景!
JavaScript 是如何工作的:Service Worker 的生命周期及使用場景!
JavaScript 是如何工作的:Web 推送通知的機(jī)制!
JavaScript 是如何工作的:使用 MutationObserver 跟蹤 DOM 的變化!
JavaScript 是如何工作的:渲染引擎和優(yōu)化其性能的技巧!
JavaScript 是如何工作的:深入網(wǎng)絡(luò)層 + 如何優(yōu)化性能和安全!
JavaScript 是如何工作的:CSS 和 JS 動畫底層原理及如何優(yōu)化它們的性能!
JavaScript 是如何工作的:解析、抽象語法樹(AST)+ 提升編譯速度5個(gè)技巧!
JavaScript 是如何工作的:深入類和繼承內(nèi)部原理+Babel和 TypeScript 之間轉(zhuǎn)換!
JavaScript 是如何工作的:存儲引擎+如何選擇合適的存儲API!
JavaScript 是如何工作的:Shadow DOM 的內(nèi)部結(jié)構(gòu)+如何編寫?yīng)毩⒌慕M件!
JavaScript 是如何工作的:WebRTC 和對等網(wǎng)絡(luò)的機(jī)制!
JavaScript 是如何工作的:編寫自己的 Web 開發(fā)框架 + React 及其虛擬 DOM 原理!
JavaScript 是如何工作的:模塊的構(gòu)建以及對應(yīng)的打包工具
JavaScript 是如何工作的:JavaScript 的內(nèi)存模型
關(guān)于JavaScript如何將值傳遞給函數(shù),在互聯(lián)網(wǎng)上有很多誤解和爭論。大致認(rèn)為,參數(shù)為原始數(shù)據(jù)類時(shí)使用按值傳遞,參數(shù)為數(shù)組、對象和函數(shù)等數(shù)據(jù)類型使用引用傳遞。
按值傳遞 和 引用傳遞參數(shù) 主要區(qū)別簡單可以說:
按值傳遞:在函數(shù)里面改變傳遞的值不會影響到外面
引用傳遞:在函數(shù)里面改變傳遞的值會影響到外面
但答案是 JavaScript 對所有數(shù)據(jù)類型都使用按值傳遞。它對數(shù)組和對象使用按值傳遞,但這是在的共享傳參或拷貝的引用中使用的按值傳參。這些說有些抽象,先來幾個(gè)例子,接著,我們將研究JavaScript在 函數(shù)執(zhí)行期間的內(nèi)存模型,以了解實(shí)際發(fā)生了什么。
按值傳參在 JavaScript 中,原始類型的數(shù)據(jù)是按值傳參;對象類型是跟Java一樣,拷貝了原來對象的一份引用,對這個(gè)引用進(jìn)行操作。但在 JS 中,string 就是一種原始類型數(shù)據(jù)而不是對象類。
let setNewInt = function (i) { i = i + 33; }; let setNewString = function (str) { str += "cool!"; }; let setNewArray = function (arr1) { var b = [1, 2]; arr1 = b; }; let setNewArrayElement = function (arr2) { arr2[0] = 105; }; let i = -33; let str = "I am "; let arr1 = [-4, -3]; let arr2 = [-19, 84]; console.log("i is: " + i + ", str is: " + str + ", arr1 is: " + arr1 + ", arr2 is: " + arr2); setNewInt(i); setNewString(str); setNewArray(arr1); setNewArrayElement(arr2); console.log("現(xiàn)在, i is: " + i + ", str is: " + str + ", arr1 is: " + arr1 + ", arr2 is: " + arr2);
運(yùn)行結(jié)果
i is: -33, str is: I am , arr1 is: -4,-3, arr2 is: -19,84 現(xiàn)在, i is: -33, str is: I am , arr1 is: -4,-3, arr2 is: 105,84
這邊需要注意的兩個(gè)地方:
1)第一個(gè)是通過 setNewString 方法把字符串 str 傳遞進(jìn)去,如果學(xué)過面向?qū)ο蟮恼Z言如C#,Java 等,會認(rèn)為調(diào)用這個(gè)方法后 str 的值為改變,引用這在面向?qū)ο笳Z言中是 string 類型的是個(gè)對象,按引用傳參,所以在這個(gè)方法里面更改 str 外面也會跟著改變。
但是 JavaScript 中就像前面所說,在JS 中,string 就是一種原始類型數(shù)據(jù)而不是對象類,所以是按值傳遞,所以在 setNewString 中更改 str 的值不會影響到外面。
2)第二個(gè)是通過 setNewArray 方法把數(shù)組 arr1 傳遞進(jìn)去,因?yàn)閿?shù)組是對象類型,所以是引用傳遞,在這個(gè)方法里面我們更改 arr1 的指向,所以如果是這面向?qū)ο笳Z言中,我們認(rèn)為最后的結(jié)果arr1 的值是重新指向的那個(gè),即 [1, 2],但最后打印結(jié)果可以看出 arr1 的值還是原先的值,這是為什么呢?
共享傳遞Stack Overflow上Community Wiki 對上述的回答是:對于傳遞到函數(shù)參數(shù)的對象類型,如果直接改變了拷貝的引用的指向地址,那是不會影響到原來的那個(gè)對象;如果是通過拷貝的引用,去進(jìn)行內(nèi)部的值的操作,那么就會改變到原來的對象的。
可以參考博文 JavaScript Fundamentals (2) – Is JS call-by-value or call-by-reference?
function changeStuff(state1, state2) { state1.item = "changed"; state2 = {item: "changed"}; } var obj1 = {item: "unchanged"}; var obj2 = {item: "unchanged"}; changeStuff(obj1, obj2); console.log(obj1.item); // obj1.item 會被改變 console.log(obj2.item); // obj2.item 不會被改變
緣由: 上述的 state1 相當(dāng)于 obj1, 然后 obj1.item = "changed",對象 obj1 內(nèi)部的 item 屬性進(jìn)行了改變,自然就影響到原對象 obj1 。類似的,state2 也是就 obj2,在方法里 state2 指向了一個(gè)新的對象,也就是改變原有引用地址,這是不會影響到外面的對象(obj2),這種現(xiàn)象更專業(yè)的叫法:call-by-sharing,這邊為了方便,暫且叫做 共享傳遞。
內(nèi)存模型JavaScript 在執(zhí)行期間為程序分配了三部分內(nèi)存:代碼區(qū),調(diào)用堆棧和堆。 這些組合在一起稱為程序的地址空間。
代碼區(qū):這是存儲要執(zhí)行的JS代碼的區(qū)域。
調(diào)用堆::這個(gè)區(qū)域跟蹤當(dāng)前正在執(zhí)行的函數(shù),執(zhí)行計(jì)算并存儲局部變量。變量以后進(jìn)先出法存儲在堆棧中。最后一個(gè)進(jìn)來的是第一個(gè)出去的,數(shù)值數(shù)據(jù)類型存儲在這里。
例如:
var corn = 95 let lion = 100
在這里,變量 corn 和 lion 值在執(zhí)行期間存儲在堆棧中。
堆:是分配 JavaScript 引用數(shù)據(jù)類型(如對象)的地方。 與堆棧不同,內(nèi)存分配是隨機(jī)放置的,沒有 LIFO策略。 為了防止堆中的內(nèi)存漏洞,JS引擎有防止它們發(fā)生的內(nèi)存管理器。
class Animal {} // 在內(nèi)存地址 0x001232 上存儲 new Animal() 實(shí)例 // tiger 的堆棧值為 0x001232 const tiger = new Animal() // 在內(nèi)存地址 0x000001 上存儲 new Objec實(shí)例 // `lion` 的堆棧值為 0x000001 let lion = { strength: "Very Strong" }
Here,lion 和 tiger 是引用類型,它們的值存儲在堆中,并被推入堆棧。它們在堆棧中的值是堆中位置的內(nèi)存地址。
激活記錄(Activation Record),參數(shù)傳遞我們已經(jīng)看到了 JS 程序的內(nèi)存模型,現(xiàn)在,讓我們看看在 JavaScript 中調(diào)用函數(shù)時(shí)會發(fā)生什么。
// 例子一 function sum(num1,num2) { var result = num1 + num2 return result } var a = 90 var b = 100 sum(a, b)
每當(dāng)在 JS 中調(diào)用一個(gè)函數(shù)時(shí),執(zhí)行該函數(shù)所需的所有信息都放在堆棧上。這個(gè)信息就是所謂的激活記錄(Activation Record)。
這個(gè) Activation Record,我直譯為激活記錄,找了好多資料,沒有看到中文一個(gè)比較好的翻譯,如果朋友們知道,歡迎留言。
激活記錄上的信息包括以下內(nèi)容:
SP 堆棧指針:調(diào)用方法之前堆棧指針的當(dāng)前位置。
RA 返回地址:這是函數(shù)執(zhí)行完成后繼續(xù)執(zhí)行的地址。
RV 返回值:這是可選的,函數(shù)可以返回值,也可以不返回值。
參數(shù):將函數(shù)所需的參數(shù)推入堆棧。
局部變量:函數(shù)使用的變量被推送到堆棧。
我們必須知道這一點(diǎn),我們在js文件中編寫的代碼在執(zhí)行之前由 JS 引擎(例如 V8,Rhino,SpiderMonke y等)編譯為機(jī)器語言。
所以以下的代碼:
let shark = "Sea Animal"
會被編譯成如下機(jī)器碼:
01000100101010 01010101010101
上面的代碼是我們的js代碼等價(jià)。 機(jī)器碼和 JS 之間有一種語言,它是匯編語言。 JS 引擎中的代碼生成器在最終生成機(jī)器碼之前,首先是將 js 代碼編譯為匯編代碼。
為了了解實(shí)際發(fā)生了什么,以及在函數(shù)調(diào)用期間如何將激活記錄推入堆棧,我們必須了解程序是如何用匯編表示的。
為了跟蹤函數(shù)調(diào)用期間參數(shù)是如何在 JS 中傳遞的,我們將例子一的代碼使用匯編語言表示并跟蹤其執(zhí)行流程。
先介紹幾個(gè)概念:
ESP:(Extended Stack Pointer)為擴(kuò)展棧指針寄存器,是指針寄存器的一種,用于存放函數(shù)棧頂指針。與之對應(yīng)的是 EBP(Extended Base Pointer),擴(kuò)展基址指針寄存器,也被稱為幀指針寄存器,用于存放函數(shù)棧底指針。
EBP:擴(kuò)展基址指針寄存器(extended base pointer) 其內(nèi)存放一個(gè)指針,該指針指向系統(tǒng)棧最上面一個(gè)棧幀的底部。
EBP 只是存取某時(shí)刻的 ESP,這個(gè)時(shí)刻就是進(jìn)入一個(gè)函數(shù)內(nèi)后,cpu 會將ESP的值賦給 EBP,此時(shí)就可以通過 EBP 對棧進(jìn)行操作,比如獲取函數(shù)參數(shù),局部變量等,實(shí)際上使用 ESP 也可以。
// 例子一 function sum(num1,num2) { var result = num1 + num2 return result } var a = 90 var b = 100 var s = sum(a, b)
我們看到 sum 函數(shù)有兩個(gè)參數(shù) num1 和 num2。函數(shù)被調(diào)用,傳入值分別為 90 和 100 的 a 和 b。
記住:值數(shù)據(jù)類型包含值,而引用數(shù)據(jù)類型包含內(nèi)存地址。
在調(diào)用 sum 函數(shù)之前,將其參數(shù)推入堆棧
ESP->[......] ESP->[ 100 ] [ 90 ] [.......]
然后,它將返回地址推送到堆棧。返回地址存儲在EIP 寄存器中:
ESP->[Old EIP] [ 100 ] [ 90 ] [.......]
接下來,它保存基指針
ESP->[Old EBP] [Old EIP] [ 100 ] [ 90 ] [.......]
然后更改 EBP 并將調(diào)用保存寄存器推入堆棧。
ESP->[Old ESI] [Old EBX] [Old EDI] EBP->[Old EBP] [Old EIP] [ 100 ] [ 90 ] [.......]
為局部變量分配空間:
ESP->[ ] [Old ESI] [Old EBX] [Old EDI] EBP->[Old EBP] [Old EIP] [ 100 ] [ 90 ] [.......]
這里執(zhí)行加法:
mov ebp+4, eax ; 100 add ebp+8, eax ; eax = eax + (ebp+8) mov eax, ebp+16 ESP->[ 190 ] [Old ESI] [Old EBX] [Old EDI] EBP->[Old EBP] [Old EIP] [ 100 ] [ 90 ] [.......]
我們的返回值是190,把它賦給了 EAX。
mov ebp+16, eax
EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。
然后,恢復(fù)所有寄存器值。
[ 190 ] DELETED [Old ESI] DELETED [Old EBX] DELETED [Old EDI] DELETED [Old EBP] DELETED [Old EIP] DELETED ESP->[ 100 ] [ 90 ] EBP->[.......]
并將控制權(quán)返回給調(diào)用函數(shù),推送到堆棧的參數(shù)被清除。
[ 190 ] DELETED [Old ESI] DELETED [Old EBX] DELETED [Old EDI] DELETED [Old EBP] DELETED [Old EIP] DELETED [ 100 ] DELETED [ 90 ] DELETED [ESP, EBP]->[.......]
調(diào)用函數(shù)現(xiàn)在從 EAX 寄存器檢索返回值到 s 的內(nèi)存位置。
mov eax, 0x000002 ; // s 變量在內(nèi)存中的位置
我們已經(jīng)看到了內(nèi)存中發(fā)生了什么以及如何將參數(shù)傳遞匯編代碼的函數(shù)。
調(diào)用函數(shù)之前,調(diào)用者將參數(shù)推入堆棧。因此,可以正確地說在 js 中傳遞參數(shù)是傳入值的一份拷貝。如果被調(diào)用函數(shù)更改了參數(shù)的值,它不會影響原始值,因?yàn)樗鎯υ谄渌胤剑惶幚硪粋€(gè)副本。
function sum(num1) { num1 = 30 } let n = 90 sum(n) // `n` 仍然為 90
讓我們看看傳遞引用數(shù)據(jù)類型時(shí)會發(fā)生什么。
function sum(num1) { num1 = { number:30 } } let n = { number:90 } sum(n) // `n` 仍然是 { number:90 }
用匯編代碼表示:
n -> 0x002233 Heap: Stack: 002254 012222 ... 012223 0x002233 002240 012224 002239 012225 002238 002237 002236 002235 002234 002233 { number: 90 } 002232 002231 { number: 30 } Code: ... 000233 main: // entry point 000234 push n // n 值為 002233 ,它指向堆中存放 {number: 90} 地址。 n 被推到堆棧的 0x12223 處. 000235 ; // 保存所有寄存器 ... 000239 call sum ; // 跳轉(zhuǎn)到內(nèi)存中的`sum`函數(shù) 000240 ... 000270 sum: 000271 ; // 創(chuàng)建對象 {number: 30} 內(nèi)在地址主 0x002231 000271 mov 0x002231, (ebp+4) ; // 將內(nèi)存地址為 0x002231 中 {number: 30} 移動到堆棧 (ebp+4)。(ebp+4)是地址 0x12223 ,即 n 所在地址也是對象 {number: 90} 在堆中的位置。這里,堆棧位置被值 0x002231 覆蓋。現(xiàn)在,num1 指向另一個(gè)內(nèi)存地址。 000272 ; // 清理堆棧 ... 000275 ret ; // 回到調(diào)用者所在的位置(000240)
我們在這里看到變量n保存了指向堆中其值的內(nèi)存地址。 在sum 函數(shù)執(zhí)行時(shí),參數(shù)被推送到堆棧,由 sum 函數(shù)接收。
sum 函數(shù)創(chuàng)建另一個(gè)對象 {number:30},它存儲在另一個(gè)內(nèi)存地址 002231 中,并將其放在堆棧的參數(shù)位置。 將前面堆棧上的參數(shù)位置的對象 {number:90} 的內(nèi)存地址替換為新創(chuàng)建的對象 {number:30} 的內(nèi)存地址。
這使得 n 保持不變。因此,復(fù)制引用策略是正確的。變量 n 被推入堆棧,從而在 sum 執(zhí)行時(shí)成為 n 的副本。
此語句 num1 = {number:30} 在堆中創(chuàng)建了一個(gè)新對象,并將新對象的內(nèi)存地址分配給參數(shù) num1。 注意,在 num1 指向 n 之前,讓我們進(jìn)行測試以驗(yàn)證:
// example1.js let n = { number: 90 } function sum(num1) { log(num1 === n) num1 = { number: 30 } log(num1 === n) } sum(n) $ node example1 true false
是的,我們是對的。就像我們在匯編代碼中看到的那樣。最初,num1 引用與 n 相同的內(nèi)存地址,因?yàn)?b>n被推入堆棧。
然后在創(chuàng)建對象之后,將 num1 重新分配到對象實(shí)例的內(nèi)存地址。
讓我們進(jìn)一步修改我們的例子1:
function sum(num1) { num1.number = 30 } let n = { number: 90 } sum(n) // n 成為了 { number: 30 }
這將具有與前一個(gè)幾乎相同的內(nèi)存模型和匯編語言。這里只有幾件事不太一樣。在 sum 函數(shù)實(shí)現(xiàn)中,沒有新的對象創(chuàng)建,該參數(shù)受到直接影響。
... 000270 sum: 000271 mov (ebp+4), eax ; // 將參數(shù)值復(fù)制到 eax 寄存器。eax 現(xiàn)在為 0x002233 000271 mov 30, [eax]; // 將 30 移動到 eax 指向的地址
num1 是(ebp+4),包含 n 的地址。值被復(fù)制到 eax 中,30 被復(fù)制到 eax 指向的內(nèi)存中。任何寄存器上的花括號 [] 都告訴 CPU 不要使用寄存器中找到的值,而是獲取與其值對應(yīng)的內(nèi)存地址號的值。因此,檢索 0x002233 的 {number: 90} 值。
看看這樣的答案:
原始數(shù)據(jù)類型按值傳遞,對象通過引用的副本傳遞。
具體來說,當(dāng)你傳遞一個(gè)對象(或數(shù)組)時(shí),你無形地傳遞對該對象的引用,并且可以修改該對象的內(nèi)容,但是如果你嘗試覆蓋該引用,它將不會影響該對象的副本- 即引用本身按值傳遞:
function replace(ref) { ref = {}; // 這段代碼不影響傳遞的對象 } function update(ref) { ref.key = "newvalue"; // 這段代碼確實(shí)會影響對象的內(nèi)容 } var a = { key: "value" }; replace(a); // a 仍然有其原始值,它沒有被修改的 update(a); // a 的內(nèi)容被更改
從我們在匯編代碼和內(nèi)存模型中看到的。這個(gè)答案百分之百正確。在 replace 函數(shù)內(nèi)部,它在堆中創(chuàng)建一個(gè)新對象,并將其分配給 ref 參數(shù),a 對象內(nèi)存地址被重寫。
update 函數(shù)引用 ref 參數(shù)中的內(nèi)存地址,并更改存儲在存儲器地址中的對象的key屬性。
總結(jié)根據(jù)我們上面看到的,我們可以說原始數(shù)據(jù)類型和引用數(shù)據(jù)類型的副本作為參數(shù)傳遞給函數(shù)。不同之處在于,在原始數(shù)據(jù)類型,它們只被它們的實(shí)際值引用。JS 不允許我們獲取他們的內(nèi)存地址,不像在C與C++程序設(shè)計(jì)學(xué)習(xí)與實(shí)驗(yàn)系統(tǒng),引用數(shù)據(jù)類型指的是它們的內(nèi)存地址。
原文:https://blog.bitsrc.io/master...
代碼部署后可能存在的BUG沒法實(shí)時(shí)知道,事后為了解決這些BUG,花了大量的時(shí)間進(jìn)行l(wèi)og 調(diào)試,這邊順便給大家推薦一個(gè)好用的BUG監(jiān)控工具 Fundebug。
你的點(diǎn)贊是我持續(xù)分享好東西的動力,歡迎點(diǎn)贊!
交流干貨系列文章匯總?cè)缦拢X得不錯(cuò)點(diǎn)個(gè)Star,歡迎 加群 互相學(xué)習(xí)。
https://github.com/qq44924588...
我是小智,公眾號「大遷世界」作者,對前端技術(shù)保持學(xué)習(xí)愛好者。我會經(jīng)常分享自己所學(xué)所看的干貨,在進(jìn)階的路上,共勉!
關(guān)注公眾號,后臺回復(fù)福利,即可看到福利,你懂的。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/103591.html
摘要:它對數(shù)組和對象使用按值傳遞,但這是在的共享傳參或拷貝的引用中使用的按值傳參。例如在這里,變量和值在執(zhí)行期間存儲在堆棧中。返回值這是可選的,函數(shù)可以返回值,也可以不返回值。變量被推入堆棧,從而在執(zhí)行時(shí)成為的副本。 這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第 22 篇。 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 如果你錯(cuò)過了前面的章節(jié),可...
摘要:中所有函數(shù)的參數(shù)都是按值傳遞的。基本類型本身是按值傳遞,具有不可變性,對基本類型的修改,實(shí)質(zhì)上都是在棧內(nèi)存中創(chuàng)建了新的值。中把這種拷貝也認(rèn)為是按值傳遞。 本文共 1200 字,讀完只需 5 分鐘 概述 參數(shù)的傳遞分為按值傳遞和按引用傳遞,而 JavaScript 中參數(shù)的傳遞只有按值傳遞。 ECMAScript 中所有函數(shù)的參數(shù)都是按值傳遞的。 所謂按值傳遞就是: 把函數(shù)外部的值復(fù)制給...
摘要:最早由在年的語言中提出。該求值策略被用于等多種語言。該策略的重點(diǎn)是調(diào)用函數(shù)傳參時(shí),函數(shù)接受對象實(shí)參引用的副本既不是按值傳遞的對象副本,也不是按引用傳遞的隱式引用。它和按引用傳遞的不同在于在共享傳遞中對函數(shù)形參的賦值,不會影響實(shí)參的值。 周五晚上下班回家的路上,突然想到了 CommonJS 規(guī)范、Node.js 模塊化等等各種東西,然后就想到了熟悉的 module.exports。 大約...
摘要:為了方便大家共同學(xué)習(xí),整理了之前博客系列的文章,目前已整理是如何工作這個(gè)系列,可以請猛戳博客查看。以下列出該系列目錄,歡迎點(diǎn)個(gè)星星,我將更友動力整理理優(yōu)質(zhì)的文章,一起學(xué)習(xí)。 為了方便大家共同學(xué)習(xí),整理了之前博客系列的文章,目前已整理 JavaScript 是如何工作這個(gè)系列,可以請猛戳GitHub博客查看。 以下列出該系列目錄,歡迎點(diǎn)個(gè)星星,我將更友動力整理理優(yōu)質(zhì)的文章,一起學(xué)習(xí)。 J...
摘要:按引用傳遞時(shí),函數(shù)的形參接收實(shí)參的隱式引用,而不再是副本。探究值的傳遞方式的基本類型,是按值傳遞的。但這樣是否說明的對象是按引用傳遞的呢我們再看下面的例子仍然是并未被修改為如果是按引用傳遞,修改形參的值,應(yīng)該影響到實(shí)參才對。 最近遇到個(gè)有趣的問題:JS中的值是按值傳遞,還是按引用傳遞呢? 在分析這個(gè)問題之前,我們需了解什么是按值傳遞(call by value),什么是按引用傳遞(ca...
閱讀 2435·2021-10-09 09:44
閱讀 3792·2021-09-22 15:43
閱讀 2924·2021-09-02 09:47
閱讀 2539·2021-08-12 13:29
閱讀 3871·2019-08-30 15:43
閱讀 1680·2019-08-30 13:06
閱讀 2189·2019-08-29 16:07
閱讀 2745·2019-08-29 15:23