(注1:如果有問題歡迎留言探討,一起學(xué)習(xí)!轉(zhuǎn)載請注明出處,喜歡可以點個贊哦?。?br> (注2:更多內(nèi)容請查看我的目錄。)
1. JS的數(shù)據(jù)類型
JS變量的數(shù)據(jù)類型的值有兩種:基本類型值和引用類型值。基本類型值指簡單的數(shù)據(jù)段,而引用類型值指那些可能由多個值構(gòu)成的對象。
基本類型值有以下五種:Undefined、Null、Boolean、Number和String。引用類型值即保存在內(nèi)存中的對象。
var num1 = 1;
var str1 = '1';
var obj1 = {a: 1};
2. JS的變量復(fù)制
JS對基本類型的復(fù)制和引用類型的復(fù)制并不相同。基本類型值的復(fù)制實際上將變量和其存儲的內(nèi)容重新復(fù)制了一份,而引用類型的復(fù)制只是將其保存的指針復(fù)制了一份,實際存儲對象的堆并沒有復(fù)制。
var num1 = 6;
var num2 = num1;
var obj1 = {a: 1};
var obj2 = obj1;
3. JS的參數(shù)傳遞是按值傳參
JS的參數(shù)是按值傳遞,即將函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部的參數(shù),其復(fù)制過程如前所述。那么對內(nèi)部變量值的改變是否會影響外部變量呢,這里我們用具體的例子來分析一下。
function addTen(num) {
num += 10;
return num;
}
var count = 20;
var result = addTen(count);
alert(count); //20 沒有改變
alert(result); //30
我們可以看到,基本類型變量的傳參對原變量并無影響,這一點大家也容易理解??墒菍σ妙愋偷膫鲄⒛??
// eg3.1
function setName(obj) {
obj.name = "Nicholas";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
我們發(fā)現(xiàn)原始變量person對象的name屬性被改變了,這具有很強的迷惑性,會讓人以為引用類型的傳參是將整個引用對象存儲的內(nèi)容復(fù)制傳遞了。是否如此呢?我們看下面這個例子。
// eg3.2
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
如果真的是按引用傳遞,那么最后person.name應(yīng)該是'Greg'才對,但事實上卻是'Nicholas',說明這里是并不是按引用傳遞。下面我們來一步步分析這兩段代碼的實際過程。
對于eg3.1和eg3.2:
step1: var person = new Object();執(zhí)行完如下:
step2: 進入setName(person);如下:
step3: obj.name = "Nicholas";執(zhí)行完如下:
eg3.1的setName函數(shù)調(diào)用到此已結(jié)束,此時,person.name從圖中可以看出是'Nicholas'。而對于eg3.2,其setName函數(shù)增加了兩個步驟,如下:
step4: obj = new Object();執(zhí)行完如下:
step5: obj.name = "Greg";執(zhí)行完如下:
可以看到,此時person.name仍然是'Nicholas'。
現(xiàn)在,我們明白了,其實JS函數(shù)參數(shù)的傳遞始終是按值傳遞。但是在函數(shù)調(diào)用的過程中,我們到底是對該值指向的堆地址進行了操作,還是對該值進行了操作,決定了我們是否會對原變量產(chǎn)生影響。
4. 測試一下
看到這里,你應(yīng)該已經(jīng)掌握了JS的數(shù)據(jù)類型和按值傳遞。來做一個小測驗,下面是兩個對數(shù)組進行拼接并返回拼接后數(shù)組的函數(shù),哪個函數(shù)在拼接的同時對傳入的參數(shù)也產(chǎn)生了影響呢?(順便學(xué)習(xí)一下es6的知識吧b( ̄▽ ̄)d)
var fillArray = (arr, ...values) => {arr.push(...values);return arr;}
var fillArray = (arr, ...values) => {arr = arr.concat(...values);return arr;}
參考
BOOK-《JavaScript高級程序設(shè)計(第3版)》 第3章