JavaScript的進階之路(二)函數簡介,變量、作用域和內存問題
<h3>ECMAScript中函數不存在函數簽名的概念,沒有重載</h3>
<h3>無需指定返回值,可以在任何時候返回任何值。未指定返回值的函數,返回的是一個特殊的undefined值</h3>
<script type="text/javascript"> function sayHi(){ console.log("Hi"); }; sayHi(); function sayName(name,age){ console.log("我是"+name+",我今年"+age+"歲了!"); }; sayName("吳瓊",18); function sum(num1,num2){ return num1+num2; alert("我不會被執行到!"); //位於return語句之後的任何代碼都不會執行。 } sum(1,2); function compare(n1,n2){ if(n1<n2){ console.log(n1+"小於"+n2); }else if(n2<n1){ console.log(n2+"小於"+n1); }else{ console.log("他們倆相等!"); } } compare(2,2); </script>
<h1>基本類型和引用類型的值</h1>
<h3>在操作對象時,實際上是在操作對象的引用,而不是實際的對象。</h3>
<h3 class="red">基本類型具有動態的值,引用類型具有動態的屬性。</h3>
<h3 class="red">復制變量值:基礎類型是復制一個新值;引用類型是復制一個指針。</h3>
<h3 class="red">傳遞參數:可以把函數的參數當成一個局部變量。基本類型傳遞參數是復制值給一個局部變量,引用類型傳遞參數是復制一個地址給變量對象;</h3>
<h2 class="red">之前說到函數的參數是按值傳遞的,那麽復制的這個地址可以當做一個值嗎?答案:可以。為什麽?</h2>
<h3>檢測變量:typeof 操作符可以確定一個變量是字符串、數值、布爾值,還是undefined的最佳工具。檢測對象時,用instanceof操作符。</h3>
<h1>執行環境(也稱作用域)</h1>
<h3>每個環境都有一個與之關聯的變量對象。執行環境有2種:全局和局部(函數)。</h3>
<h3 class="red">作用域鏈的作用:保證 (對執行環境有權訪問的 )(所有變量和函數的) 有序訪問;</h3>
<h3>作用域鏈的前端始終都是所在環境的與之關聯的變量對象。在Web瀏覽器中,window對象始終是最頂端。</h3>
<h3>函數的參數也被當成變量來對待,訪問規則與執行環境中的其他變量相同。</h3>
<h2>延長作用域鏈</h2>
<h3>try{}catch(e){}語句的catch塊 和 with語句可以延長作用域鏈。</h3>
<h2>沒有塊級作用域:像if語句中聲明的變量和for語句中聲明的循環變量,在外部均可以訪問到;</h2>
<h3>在函數中的變量如果想在外部訪問,必須是全局變量(沒有var聲明的變量)。</h3>
<h3>在函數中的變量查找規則是從內環境到外環境。</h3>
<h1>垃圾收集:找出那些不在繼續使用的變量,然後釋放其占用的內存。常見的2個策略:標記清除和引用計數。</h1>
<h3>關於垃圾收集產生的性能問題:IE6默認值,IE7根據內存用量動態的修改值,性能比IE6大大提高。</h3>
<h3>關於管理內存:JavaScript分配給Web瀏覽器的可用內存量比分配給桌面應用程序的要少。</h3>
<h2 class="red">內存限制會影響網頁的性能:1、給變量分配的內存 2、調用棧以及在一個線程中同時執行的語句數量。</h2>
<h2 class="red">確保占用最少的內存可以讓頁面獲得更好的性能。而優化內存占用的最佳方式就是為執行中的代碼只保存必要的數據。</h2>
<h2 class="red">解除引用:將用不到的全局變量設置為null來釋放其引用。此時,並沒有釋放內存,只是讓值脫離了執行環境,下次垃圾回收時再釋放。</h2>
<script type="text/javascript"> var a=1; var b=a; delete a; console.log(b); //a對b沒有任何影響 var obj1=new Object(); var obj3=new Object(); var obj2=obj1; obj1.name="吳瓊"; console.log(obj2.name); obj2.name="張虹"; console.log(obj1.name); console.log(obj3.name); var num = 1; function add(sum){ sum+=10; console.log(sum); }; add(num); // 基本類型傳遞參數是把變量num的值復制給一個局部變量sum; console.log(num); //變量的值並沒有改變 function odd(obj){ obj.name="吳瓊"; } var person = new Object(); odd(person); console.log(person.name); function odd2(obj){ obj.name="吳瓊"; var obj = new Object(); //在函數內的變量引用的是一個局部對象,在函數執行完畢後會立即被銷毀; obj.name="張虹"; }; var person2=new Object(); odd(person2); //把person2傳遞給odd2()方法後,其name屬性的值被定義為“吳瓊”,如果是按引用傳遞的,則obj的name會被修改; console.log(person2.name); console.log(odd instanceof Function); //測試沒有塊級作用域 if(true){ var color = "red"; } console.log(color); // red//測試沒有塊級作用域 for(var i=0;i<10;i++){ // }; console.log(i); //10 //測試沒有塊級作用域 //函數中的變量在外部訪問 var sum; function fn(num1,num2){ sum = num1+num2; }; fn(1,2); console.log(sum); //如果函數內聲明var sum 則報錯sum is not defind //作用域鏈的查詢 var col = "black"; function getCol(){ var col = "blue"; //從內到外查找 如果有這個聲明,則 blue return col; } console.log(getCol()); //blue getCol(); //執行方法後,函數內用var 聲明的變量依然為局部變量 console.log(col);//black </script>
JavaScript的進階之路(二)函數簡介,變量、作用域和內存問題