JavaScript的賦值是引用or複製,及參數傳遞

先來看2014年阿里巴巴前端線上筆試題:前端

var a = 1;
var obj = {
    b: 2
};
var fn = function () {};
fn.c = 3;

function test(x, y, z) {
    x = 4;
    y.b = 5;
    z.c = 6;
    return z;
}
test(a, obj, fn);
alert(a + obj.b + fn.c);

答案是12,若是回答得正確,就不必看下去。If not,就跟我一塊兒來學習下好啦~面試

(一)基本類型函數

因爲學js沒多久,對賦值到底是引用仍是複製不是很清楚(若是是引用,那一個值改變會影響另外一個,若是是複製,那各玩各的,互不影響),遇到這類問題每每就很迷糊。花了半天時間參閱了一些資料,整理以下。學習

首先,JavaScript的基本類型有boolean, string, number,還有undefined和null,啊你確定會說幹嗎又扯最無聊的any book的語法第一章內容,瞭解這個又怎麼樣,還真的有用呢。首先得明白的是,只有字面量的boolean,string和number,以及undefined + null(exact undefined null,區分大小寫)纔是屬於基本類型的,new出來的不算。spa

即:code

alert(typeof false);//"boolean"
var b = new Boolean(false);
alert(typeof b);//"object"

一樣,new String('aaa')這種都不是基本類型,直接的a = 'aaa',a是基本類型,這就是:字面量的纔是基本類型。對象

另外一方面,Object,Function,Array其實都是構造函數,由於能夠直接new Object()等,因此它們都是函數,so (Object instanceof Function === true) &&(Function instanceof Object===true).blog

要注意的是,基本類型沒有屬性和方法,但它們能夠調用對應基本包裝類型的方法,能夠來看下面的例子:ip

var a = 'ot';
a.age = 18;//hahahahaha, yeah, forever 18
alert(a.age);//undefined
a.length = 160;
alert(a.length);//2

第二步的a.age = 18其實在實現的時候分紅三步:內存

var s1 = new String('ot');
s1.age = 18;
s1 = null;

即基本類型每次調用類型或方法都會建立新對象,隨後便銷燬。

一樣,在alert(a.age)的時候,分爲下列步驟:

var s2 = new String('ot');
alert(s2.age);
s2 = null;

由於沒有對s2定義age方法,因此輸出爲undefined。在alert(a.length)的時候,因爲s3 = new String('ot'),String有length方法,因此,會輸出結果,固然,上一步的賦值操做的對象也必定已經被銷燬了。

(二)引用or Copy

Clear about基本類型後,要了解的是,基本類型變量存在棧內部,每賦值一次就建立一個新的copy,而後play with itself. 而除了基本類型以外的引用類型,則存在堆內存中,只能引用。能夠來看下面的例子:

var ot = new Object();//建立一個對象,把地址賦值給ot,即ot指向這個地址
var op = ot;//把ot的值賦給op,因此op也是指向那個對象
op.age = 18;
alert(ot.age);//18

op = new String('sunshine');//把新建立對象的地址賦給op, ot固然不變
alert(ot.length);//undefined

看了註釋部分,相信已經能理解了。

(三)參數傳遞

Javascript的參數傳遞爲值傳遞,咱們來看下面的例子:

function setAge(i)
{
    alert(i);//24
    i = 18;
    alert(i);//18
};

var ot = 24;
setAge(ot);

alert(ot);//24

把ot的值24傳遞進去,賦值給i,因而第一個alert的是24,而後i從新賦值,因而alert出來的是18,但外層的ot不受影響,由於傳遞值,也就是複製了分內容給i而已。

那傳遞的值爲引用類型時會怎麼樣呢?先看例子:

function setName(obj)
{
    obj.name = 'ot';
};

var obj2 = new Object();
setName(obj2);
alert(obj2.name);//ot

這看起來很像是傳遞的是引用,由於obj.name受到改變了,但其實不是,其實仍是值,由於obj2自己的值就是新對象的地址,因此傳進去的就是這個地址。

(四)回到面試題

咱們如今再來看前面的面試題:

var a = 1;
var obj = {
    b: 2
};
var fn = function () {};
fn.c = 3;

function test(x, y, z) {
    x = 4;
    y.b = 5;
    z.c = 6;
    return z;
}
test(a, obj, fn);
alert(a + obj.b + fn.c);

首先test傳遞進去的實參中,a是基本類型(啊對了,複製了一份值喔喔),obj是object(指向地址呼啦啦,你動我也動呢),fn也固然不是基本類型啦。在執行test的時候,x被賦值爲4(跟a不要緊,各玩各的嘛,a仍然爲1),y的b被賦值爲5,那obj的b也變爲5,z的c變爲6,那fn的c固然也會是6. 因此alert的結果應該是1+5+6 =12. (其實test不返回z也同樣,z仍然改變的)。

相關文章
相關標籤/搜索