摘要:中所有函數的參數都是按值傳遞的。基本類型本身是按值傳遞,具有不可變性,對基本類型的修改,實質上都是在棧內存中創建了新的值。中把這種拷貝也認為是按值傳遞。
本文共 1200 字,讀完只需 5 分鐘概述
參數的傳遞分為按值傳遞和按引用傳遞,而 JavaScript 中參數的傳遞只有按值傳遞。
ECMAScript 中所有函數的參數都是按值傳遞的。
所謂按值傳遞就是:
把函數外部的值復制給函數內部的參數,就和把值從一個變量復制到另一個變量一樣。 -- 《JavaScript 高級程序設計》
我們知道 JS 中,既有基本數據類型又有引用數據類型,那么二者的按值傳遞有什么樣的區別呢?
先給結論
在向參數傳遞基本數據類型時,被傳遞的值會被復制給一個局部變量(arguments 類數組對象中的一個元素)。在向參數傳遞引用數據類型時,會把這個值的內存地址賦給一個局部變量。一、數據類型
在 JS 中,數據類型分為基本類型和引用類型。
其中基本類型包括:number, string, boolean, undefined, null, Symbol(es 6 新增)。基本類型的值是保存在棧內存當中的。
基本數據類型的值本身是不會改變的。
let num1 = 5; let num2 = num1;
將保存著原始值的變量 num1 賦值給 num2 后,會將原始值 num1 的副本賦值給新變量 num2, 此后這兩個變量是完全獨立的,他們只是擁有相同的值而已,是完全獨立的拷貝,互不干涉。
引用數據類型包括:Function, Array, Object 等等除了基本數據類型之外的數據。引用數據類型是保存在堆內存當中的。
JS 不允許直接操作對象的內存空間,所以引用數據類型是通過存儲在變量處的值,也就是一個指針(point),指向存儲對象的內存地址,從而進行訪問的。
let obj1 = new Object(); var obj2 = obj1;
當把引用類型的變量 obj1 賦給另一個變量 obj2 后,obj2 接受的其實是引用類型數據的內存地址指針。所以,判斷兩個引用類型是否相等,其實比較的是內存地址是否相等。
二、按值傳遞var num = 1; function foo(param) { param = 2; } foo(num); console.log(num); // num 值仍為1, 并沒有受 param = 2 賦值影響
以上代碼:
按值傳遞每次傳遞參數時,都會拷貝一份副本到函數內部,拷貝前后的兩個值互不影響。
二、“按引用傳遞”var obj = { num: 1 }; function foo(o) { o.num = 2; console.log(obj.num); // 2 } foo(obj); console.log(obj.num); // 2
以上代碼,foo 函數把 obj 對象作為實參,執行完畢后把 obj 對象的 num 屬性給改變了,說明參數 o 對象 和 外部變量 obj 對象是同一個對象。說好的按值傳遞呢,怎么還是把原來的對象給改變了呢。
三、按共享傳遞再看下面這段代碼:
var obj = { num: 1 }; function foo(o) { o = 100; } foo(obj); console.log(obj.num); // 1
如果是按引用傳遞的話,按理來說 obj 對象會被改變會 100 才對。
準確的說,JS中的基本類型按值傳遞,對象類型按共享傳遞的(call by sharing,也叫按對象傳遞、按對象共享傳遞)
在共享傳遞中對函數形參的賦值,不會影響實參本身的值。
所以,形參引用的對象是同一個,由于對象是可變的(mutable),修改形參中對象的屬性值,會影響到原本對象的屬性值。
按引用傳遞是傳遞對象的引用,而按共享傳遞是傳遞對象的拷貝的副本,所以副本本身無法直接修改。而拷貝副本也是一種拷貝,所以也被認為是按值傳遞。
基本類型本身是按值傳遞,具有不可變性(immutable),對基本類型的修改,實質上都是在棧內存中創建了新的值。
復習鞏固:
var obj = { num : 0 }; obj.num = 100; var o = obj; o.num = 1; obj.num; // 1, 被修改 o = true; obj.num; // 1, o 是對象的一個拷貝,對 o 本身的修改,不會改變 obj 對象本身的值。總結
JavaScript 中參數的傳遞只有按值傳遞,而對于引用類型的傳遞,是一種共享傳遞,傳遞的是數據類型的拷貝副本,雖然引用的是同一個對象,但是無法通過改變形參來改變實參本身。
JS 中把這種拷貝也認為是按值傳遞。
歡迎關注我的個人公眾號“謝南波”,專注分享原創文章。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98641.html
摘要:按位取反按位取反運算符,對一個表達式執行位非求非運算。如果語句后面不使用標簽,則只能進入下一輪的內層循環。語句用于立即終止本輪循環,返回循環結構的頭部,開始下一輪循環。代表的是分組,即小括號里面的小正則捕獲到的內容。 JS按位取反 Javascript 按位取反運算符 (~) ,對一個表達式執行位非(求非)運算。如 ~1 = -2; ~2 = -3;來看看~1的計算步驟: 將1(這里...
摘要:深入系列第九篇,除了按值傳遞引用傳遞,還有第三種傳遞方式按共享傳遞定義在高級程序設計第三版,講到傳遞參數中所有函數的參數都是按值傳遞的。 JavaScript深入系列第九篇,除了按值傳遞、引用傳遞,還有第三種傳遞方式 —— 按共享傳遞 定義 在《JavaScript高級程序設計》第三版 4.1.3,講到傳遞參數: ECMAScript中所有函數的參數都是按值傳遞的。 什么是按值傳遞呢?...
摘要:關于的求值策略,問中函數的參數傳遞是按值傳遞還是按引用傳遞回答很經典。所以不能說中函數的參數傳遞嚴格按值傳遞或按引入傳遞。中還采用一種參數傳遞策略,叫按共享傳遞。中參數是必須先求值再作為實參傳入函數的。參考求值策略中函數參數的默認值 最近在研究 lambda 演算中的 η-變換 在 JavaScript 中的應用,偶然在 stackoverflow 上看到一個比較有意思的問題。關于 J...
摘要:棧內存與堆內存簡單類型的值,它們的值直接存儲在變量訪問的位置,這是因為這些簡單類型占據的空間是固定的,所以可將他們存儲在較小的內存區域棧中。 看到一個這樣的問題 function setName(obj) { obj.name = Tom; obj = new Object(); obj.name = Greg ; } var person = new Object();...
閱讀 745·2021-10-09 09:44
閱讀 2024·2021-09-22 15:54
閱讀 5064·2021-09-22 10:55
閱讀 1445·2019-08-29 18:41
閱讀 781·2019-08-29 11:24
閱讀 2106·2019-08-28 18:20
閱讀 1032·2019-08-26 11:51
閱讀 3052·2019-08-26 11:00