萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> Javascript的賦值是引用or復制,及參數傳遞

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出來的不算。   即:   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).   要注意的是,基本類型沒有屬性和方法,但它們可以調用對應基本包裝類型的方法,可以來看下面的例子:   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仍然改變的)。
copyright © 萬盛學電腦網 all rights reserved