Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
avaScript中除了自定義函數之外,還有匿名函數?什么是匿名函數?
1. 匿名函數:沒有函數名稱的函數。
如:定義一個匿名函數,打印5個星星。
<script>
function (){ //沒有函數名稱
for(var i=0;i<5;i++){
document.write("*");
}
}
</script>
2. 調用匿名函數有2種方法:
(1) 通過變量名調用匿名函數可以理解為將整個匿名函數瀆職給一個變量
然后在body標簽中,定義一個按鈕:
(2) 事件名調用匿名函數
同樣在在body標簽中,先定義一個按鈕:注意在input標簽中我們不通過onclick來調用匿名函數
然后我們通過2個事件調用2個匿名函數:
注意:window.onload:頁面加載時觸發的事件,這里也就是頁面加載進來調用第一匿名函數
document.getElementById("btn"):獲取id為btn的元素,也就是將按鈕獲取過來;document.getElementById("btn").onclick:點擊按鈕時,觸發第二個匿名函數
有兩種方式:1、函數聲明2、函數表達式 函數聲明會提升 ,函數表達式不會。閉包是指有權訪問另一個函數作用域中的變量的函數,創建閉包的常見方式,是在一個函數內部創建另一個函數,通過另一個函數訪問這個函數的局部變量。由于作用域鏈的機制導致一個問題,循環里的 匿名函數取得的任何變量都是最后一個值。閉包所保存的是整個變量對象,而不是某個特殊的變量。this對象 this對象是在運行時基于函數的執行環境綁定的,如果this在全局范圍就是window,如果在對象內部就指向這個對象。而閉包卻在運行時指向window,因為閉包并不屬于這個對象的屬性或方法。
有兩種方式:1、函數聲明2、函數表達式
函數聲明會提升,函數表達式不會。
函數聲明,在執行函數之前會先讀取函數聲明。
sayhi()//‘hi’ function sayhi(){ console.log('hi'); } //不會出錯
函數表達式
sayhi()//‘hi’ var sayhi=function(){ console.log('hi'); } //會出錯
函數表達式和函數聲明中沒有函數名的函數,都是匿名函數
//不要這樣做!,有的瀏覽器用第一個聲明,有的用第二個 if(condition){ function sayHi(){ alert("Hi!"); } } else { function sayHi(){ alert("Yo!"); } } //可以這樣做 var sayHi; if(condition){ sayHi = function(){ alert("Hi!"); }; } else { sayHi = function(){ alert("Yo!"); }; }
閉包是指有權訪問另一個函數作用域中的變量的函數,創建閉包的常見方式,是在一個函數內部創建另一個函數,通過另一個函數訪問這個函數的局部變量。
閉包可以讓外側函數的局部變量駐留內存,實現局部變量的累加,過度使用閉包導致性能下降,內存泄漏
function a(){ var age=1; return function(){ age++; return age; } } var x=a(); console.log(x())//2 console.log(x())//3
由于作用域鏈的機制導致一個問題,循環里的匿名函數取得的任何變量都是最后一個值。閉包所保存的是整個變量對象,而不是某個特殊的變量。
function box() { var arr = []; for (var i = 0; i < 5; i++) { arr[i] = function() { return i; }; } return arr; } var b = box(); //得到函數數組 alert(b.length); //得到函數集合長度 for (var i = 0; i < b.length; i++) { console.log(b[i]()); //輸出每個函數的值,都是最后一個值55555 }
因為b中存的是匿名函數對象,當bi執行匿名函數時,box()中的for循環早已執行完畢,i早已變成5.
解決方法1:讓匿名函數自我執行
function box() { var arr = []; for (var i = 0; i < 5; i++) { arr[i] = (function(i) { return i; })(i); } return arr; } var b = box(); //得到函數數組 alert(b.length); //得到函數集合長度 for (var i = 0; i < b.length; i++) { console.log(b[i]); //輸出0,12,3,4 }
解決方法2:匿名函數下在創建一個匿名函數,外側匿名函數自執行
function box() { var arr = []; for (var i = 0; i < 5; i++) { arr[i] = (function(num) { return function() { return num;//具體數字 }; })(i) } return arr; } var b = box(); //得到函數數組 alert(b.length); //得到函數集合長度 for (var i = 0; i < b.length; i++) { console.log(b[i]()); //輸出 01234 }
this對象是在運行時基于函數的執行環境綁定的,如果this在全局范圍就是window,如果在對象內部就指向這個對象。而閉包卻在運行時指向window,因為閉包并不屬于這個對象的屬性或方法。
var user='window'; var obj={ user:'obj', getUserName:function(){ return function(){ return this.user; } } } console.log(obj.getUserName()());//window
解決1:強制指向特定對象
console.log(obj.getUserName().call(obj));//obj console.log(obj.getUserName().apply(obj));//obj
解決2:復制this,得到上一個作用域的this對象
var user='window'; var obj={ user:'obj', getUserName:function(){ var that=this; return function(){ return that.user; } } } console.log(obj.getUserName()());//obj
for循環中的var i
在外部也能訪問
function box(count) { for (var i=0; i<count; i++) {} var i; //就算重新聲明,也不會覆蓋前面的值,除非重新初始化 alert(i); } box(2);//2
解決1:
//模仿塊級作用域(私有作用域)
(function () {
//這里是塊級作用域
})();
//使用塊級作用域(私有作用域)改寫 function box(count) { (function () { for (var i = 0; i<count; i++) {} })(); alert(i); //報錯,無法訪問 } box(2);
解決2:ES6中使用let
function box(count) { for (let i=0; i<count; i++) {} alert(i); //i報錯 } box(2);
參考資料:JavaScript高級程序設計(第3版)
數的編寫與使用
在程序設計語言中函數是一段具有特殊功能的代碼,同時也是一組可以重復使用的代碼。通過函數這一對象的使用,進一步提高了程序開發的模塊化與高度多的代碼復用性。各種程序設計語言都對函數的定義及使用有著嚴格的語法規則。本文主要介紹如何在JavaScript中定義函數、使用函數,并對遞歸函數這一特殊類型函數進行說明。
JavaScript中所定義的函數主要由函數定義關鍵字、函數名稱、函數參數、執行代碼段與函數返回值5部分所組成。同時要求函數在使用過程中需要先定義函數,再調用函數。JavaScript函數定義基本語法描述如下:
JavaScript函數定義基本語法
JavaScript函數定義基本語法描述如上圖,說明如下:
函數定義語法說明
函數定義完成之后,就可以通過調用該函數完成特定的功能。函數調用方式較為簡單,只需要給出函數名稱與所傳遞參數,如果參數為空,只需要給出名稱后面的括號即可。關于參數部分需要注意形參與實參概念的區分。其中在函數定義中用于解釋說明語言的參數為形參。在函數調用過程中替代形參參與實際運算的參數為實參。示例說明如下:
形參與實參示例說明
匿名函數(Anonymous function),顧名思義是指沒有名字的函數,即在上面給出的基本語法中functionName部分可以省略的函數。在JavaScript中提供兩類基本匿名函數定義方式,一種是將匿名函數封裝為表達式,一種是將匿名函數賦值給變量形式。兩類匿名函數基本語法描述如下:
匿名函數的定義形式
匿名函數定義形式描述如上圖所示,上文中計算解決值函數我們可以使用兩種方法改寫為匿名函數,實現描述如下:
匿名函數使用實例
遞歸函數是一類特殊的函數類型,簡單理解即為在一個函數的內部調用了該函數自身。在使用遞歸函數是需要注意產生遞歸的條件與遞歸終止的條件。如同循環控制語句一樣,沒有遞歸終止的條件,程序將會一直占用資源,無法結束釋放資源。遞歸函數的說明可以從階乘的計算這一案例展開說明。階乘計算過程描述如下:
階乘計算原理
階乘計算過程描述如上圖所示,我們可知階乘問題的解決主要在于遞推關系的挖掘與終止條件的確定。本例中遞推關系為N!=N*(N-1)!,終止條件為1!=1;在明確這兩點之后我們可以編寫遞歸函數實現問題求解。遞歸函數描述如下圖:
階乘問題的遞歸求解編程實現
爬樓梯問題是使用遞歸算法進行問題求解的經典案例之一,爬樓梯問題主要只是假設有N階樓梯,需要從最底層爬到最高層,在上樓過程中每步只允許上1層或者2層,計算爬到N層總共方法有多少種?
爬樓梯方法問題
爬樓梯方法問題采用遞歸思想還是比較簡單的,我們可以從小人最后一步考慮。小人上到最高層N層時只能有兩種方法:
①從N-2層跨越2層到達N層;
②從N-1層跨越1層到達N層;
則計算到達N層的方法f(n)就等于到達N-1層方法f(n-1)與達N-2層方法f(n-2)之和。這就找到了我們進行遞推的關系式,終止條件即為f(1)=1和f(2)=2;
因此我們可以編程實現計算,實現代碼如下:
爬樓梯遞歸求解代碼
本頭條號長期關注編程資訊分享;編程課程、素材、代碼分享及編程培訓。如果您對以上方面有興趣或代碼錯誤、建議與意見,可以聯系作者,共同探討。更多程序設計相關教程及實例分享,期待大家關注與閱讀!JavaScript基礎教程系列教程鏈接如下:
JavaScript基礎教程(六)流程控制之循環語句
JavaScript基礎教程(五)流程控制之條件語句
*請認真填寫需求信息,我們會在24小時內與您取得聯系。