先來看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仍然改變的)。