基本類型、引用類型
閑扯完了,開始寫今天要總結的基礎知識。
基本類型: undefined、Null、Boolean、Number、String五種 (簡單的數據段);
引用類型: object (由多個值構成)。
兩種類型在使用上的區別:
復制變量
這塊好理解,看一個例子的對比就秒懂:
// 基本類型 var num1 = 5; var num2 = num1; num2 = 10; console.log(num1 + ' | ' + num2); // 5 | 10 // 引用類型 var obj1 = new Object(); obj1.num = 5; var obj2 = obj1; obj2.num = 10; console.log(obj1.num + ' | ' + obj2.num); // 10 | 10
一句話,引用類型復制的是指針的指向。
傳遞參數
剛開始看書上,說的是“按值傳遞”。然后拋出一個例子:
function addTen(num) { num += 10; return num; } var count = 20; var result = addTen(count); console.log(count + ' | ' + result); // 20 | 30
看完這個例子,秒懂按值傳遞。緊接着又來一段代碼:
function setName(obj) { obj.name = 'aaa'; return obj; } var person = new Object(); person.name = 'bbb'; var newPerson = setName(person); console.log(person.name + ' | ' + newPerson.name); // aaa | aaa
看完這個例子,我就懵逼了。這段代碼不是解釋成按引用傳遞更合理嗎?
然后又給了一個證明就算參數是引用類型也是按值傳遞的例子:
function setName(obj) { obj.name = 'aaa'; var obj = new Object(); // 如果是按引用傳遞的,此處傳參進來obj應該被重新引用新的內存單元 obj.name = 'ccc'; return obj; } var person = new Object(); person.name = 'bbb'; var newPerson = setName(person); console.log(person.name + ' | ' + newPerson.name); // aaa | ccc
從結果看,並沒有顯示兩個'ccc'。這里是函數內部重寫了obj,重寫的obj是一個局部對象。當函數執行完后,立即被銷毀。
到這里,js高程解釋完了按值傳遞和按引用傳遞。然而對於我這樣智商略平的同學而言,還是一臉懵逼。於是去網上深入地了解了下。
引用值:對象變量它里面的值是這個對象在堆內存中的內存地址。因此如果按引用傳遞,它傳遞的值也就是這個內存地址。那么var obj = new Object();
會重新給obj分配一個地址,比如是0x321了,那么它就不在指向有name = 'aaa';
屬性的內存單元了。相當於把實參obj和形參obj的地址都改了,那么最終就是輸出兩個ccc了。
最后看個例子,弄懂了也就差不多理解了。
# 作者信息
var a = { num:'1' }; var b = { num:'2' }; function change(obj){ obj.num = '3'; obj = b; return obj.num; } var result = change(a); console.log(result + ' | ' + a.num); // 2 | 3
走一遍思路:
首先把a的值傳到change函數內,obj.num = '3';
后a.name
被修改為3;
a的地址被換成b的地址;
返回此時的a中a.num
。
按共享傳遞
在網上還看到一種叫 按共享傳遞 的說法,而且特別好理解。
大致概念是這樣的:調用函數傳參時,函數接受對象實參引用的副本(既不是按值傳遞的對象副本,也不是按引用傳遞的隱式引用)。 它和按引用傳遞的不同在於:在共享傳遞中對函數形參的賦值,不會影響實參的值。