JavaScript之按值傳遞

本文共 1200 字,讀完只需 5 分鐘javascript

概述

參數的傳遞分爲按值傳遞按引用傳遞,而 JavaScript 中參數的傳遞只有按值傳遞java

ECMAScript 中全部函數的參數都是按值傳遞的。數組

所謂按值傳遞就是:閉包

把函數外部的值複製給函數內部的參數,就和把值從一個變量複製到另外一個變量同樣。 -- 《JavaScript 高級程序設計》app

咱們知道 JS 中,既有基本數據類型又有引用數據類型,那麼兩者的按值傳遞有什麼樣的區別呢?函數

先給結論post

在向參數傳遞基本數據類型時,被傳遞的值會被複制給一個局部變量(arguments 類數組對象中的一個元素)。在向參數傳遞引用數據類型時,會把這個值的內存地址賦給一個局部變量。ui

1、數據類型

在 JS 中,數據類型分爲基本類型和引用類型。this

其中基本類型包括:number, string, boolean, undefined, null, Symbol(es 6 新增)。基本類型的值是保存在棧內存當中的。spa

基本數據類型的值自己是不會改變的。

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 接受的實際上是引用類型數據的內存地址指針。因此,判斷兩個引用類型是否相等,其實比較的是內存地址是否相等。

2、按值傳遞

var num = 1;
function foo(param) {
    param = 2;
}
foo(num);
console.log(num); // num 值仍爲1, 並無受 param = 2 賦值影響
複製代碼

以上代碼:

按值傳遞每次傳遞參數時,都會拷貝一份副本到函數內部,拷貝先後的兩個值互不影響。

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 對象是同一個對象。說好的按值傳遞呢,怎麼仍是把原來的對象給改變了呢。

3、按共享傳遞

再看下面這段代碼:

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 中把這種拷貝也認爲是按值傳遞。

歡迎關注個人我的公衆號「謝南波」,專一分享原創文章。

掘金專欄 JavaScript 系列文章

  1. JavaScript之變量及做用域
  2. JavaScript之聲明提高
  3. JavaScript之執行上下文
  4. JavaScript之變量對象
  5. JavaScript原型與原型鏈
  6. JavaScript之做用域鏈
  7. JavaScript之閉包
  8. JavaScript之this
  9. JavaScript之arguments
  10. JavaScript之按值傳遞
  11. JavaScript之例題中完全理解this
  12. JavaScript專題之模擬實現call和apply
相關文章
相關標籤/搜索