javascript函數(聲明,傳參,返回值,遞歸)
1、函數的基本概念
- 函數:是由事件驅動的或者當他被調用時可執行的可重復使用的代碼塊。
- 空調是由遙控器控制或者當開關打開時,可運行的家用電器(工具)
特點:
- 封裝代碼----使代碼更簡潔
- 重復使用---在重復功能的時候直接調用就好
- 執行時機---隨時可以在我們想要執行的時候執行
2、函數的創建和執行
1. 函數的創建
1、聲明式
- 函數聲明的關鍵字 : function
- function 關鍵字 和 var 關鍵字的行為幾乎一致,都會在內存上開辟一塊空間,用來存儲變量之中的數據;
function 函數名( 條件 ){
代碼
}
- 規定 : 必須執行,不執行就報錯;
- 規范 : 最好執行,不執行也不會報錯,但是會讓程序有一些負面影響。
- 函數定義的規范: 函數名的首字母小寫!
- 函數的命名規則和變量命名規則完全一致;
- 函數推薦駝峰命名;
- 變量推薦_命名;
function foo(){
console.log("hello world");
}
- 函數定義了,會吧代碼 默默的放在哪里不會去執行代碼;
- 只要在程序主動調用的時候,代碼才會執行!;
- 聲明式-規定 : 不要漏掉函數的名字!;
2、賦值式
- 函數也是數據類型的一種;
- 基本類型 : 五種;
- 引用類型 : 三種 => function(){}(其中一種)
- 我們可以認為函數是一種數據;
- 賦值式函數聲明可以沒有函數名!;
- 其實就是和我們使用 var 關鍵字是一個道理了
- 首先使用 var 定義一個變量,把一個函數當作值直接賦值給這個變量就可以了
var foo = function(){
console.log("hello world");
}
- 函數定義和調用規范 : 先聲明再調用!;
var foo = function poo(){
console.log("hello world");
// 只有在這個函數里面才會使用;
}
// poo 是無法被調用 , 因為他的作用范圍是局部的;
2. 函數的執行
- 直接執行
- 通過行為執行
函數調用的兩種形式:
- 你在代碼之中調用;
- 直接寫 函數名() 就可以了
function foo(){
console.log("hello world");
}
foo();
注意:
定義完一個函數以后,如果沒有函數調用,那么寫在 {} 里面的代碼沒有意義,只有 調用以后才會執行
2. 瀏覽器在特定時機幫你調用函數!;
- 事件行為;
- html標簽進行觸發 => 瀏覽器接受 => 瀏覽器調用函數;
<button id="btn">你點我一下試試</button>
function foo(){
console.log("hello world");
}
btn.onclick = foo
// console.log(btn);
// 在點擊的時候會讓瀏覽器調用對應的函數;
// btn 就是元素的id;
// onclick 是事件行為;
3、函數的參數(重點)
- 我們在定義函數和調用函數的時候都出現過 ()
- 現在我們就來說一下這個 () 的作用
- 就是用來放參數的位置
- 參數分為兩種 行參 和 實參
// 聲明式
function fn(行參) {
// 一段代碼
}
fn(實參)
// 賦值式函數
var fn = function (行參) {
// 一段代碼
}
fn(實參)
接收:形參
- 就是在函數內部可以使用的變量,在函數外部不能使用
- 每寫一個單詞,就相當於在函數內部定義了一個可以使用的變量(遵循變量名的命名規則和 命名規范)
- 多個單詞(形參)之間以 , 分隔
// 書寫一個參數
// 聲明式
function fn(num) {
// 在函數內部就可以使用 num 這個變量
}
// 賦值式
var fn1 = function (num) {
// 在函數內部就可以使用 num 這個變量
}
// 書寫兩個參數
// 聲明式
function fun(num1, num2) {
// 在函數內部就可以使用 num1 和 num2這兩個變量
}
// 賦值式
var fun1 = function (num1, num2) {
// 在函數內部就可以使用 num1 和 num2 這兩個變量
}
- 如果只有行參的話,那么在函數內部使用的值個變量是沒有值的,也就是 undefined
- 行參的值是在函數調用的時候由實參決定的
發送:實參
- 在函數調用的時候給行參賦值的
- 也就是說,在調用的時候是給一個實際的內容的
function fn(num) {
// 函數內部可以使用 num
}
fn(100)
// 這個函數的本次調用,書寫的實參是 100
// 那么本次調用的時候函數內部的 num 就是 100
fn(200)
// 這個函數的本次調用,書寫的實參是 200
// 那么本次調用的時候函數內部的 num 就是 200
- 函數內部的行參的值,由函數調用的時候傳遞的實參決定
- 多個參數的時候,是按照順序一一對應的
function fn(num1, num2) {
// 函數內部可以使用 num1 和 num2
}
fn(100, 200)
// 函數本次調用的時候,書寫的參數是 100 和 200
// 那么本次調用的時候,函數內部的 num1 就是 100,num2 就是 200
多個參數的關系
- 原則上來說,形參和實參的數量應該一一對應
但,如果,二者數量不一致:- 形參多,實參少:多出來的形參為undefined
- 實參多,形參少:多出來的實參找arguments
- arguments是一個在函數內部才能使用的,用來保存當前函數所有實參的類數組,也叫對象
- 可以通過索引和長度來解析arguments
- 形參比實參多 :
// 參數多了怎么辦 ?
// 形參 : 變量 => 函數體之中;
// 實參數量比形參數量少; 其余未賦值的形參值都為 undefined;
function foo( a , b , c , d ){
console.log( a , b , c , d );
}
foo( 1 );
- 實參比形參多 :
- 剩下的實參都哪里去了 ?
- 剩下的參數都使用arguments關鍵字進行接收, 使用 [] 進行取出;
function foo( a ){
// console.log(a);
// 函數之中有一個關鍵字 : arguments => 接受所有的實際參數;
// arguments 里面可以存很多很多的數據;
// console.log( arguments );
// 想要取出復雜結構之中的數據 : 取出運算符 => .
// arguments.0
// Uncaught SyntaxError: Unexpected number
// 語法報錯 : 不允許使用數字;
// JS之中的取出運算符 => .純英文
// => [] 里面可以放任何數據;
// document.write() === document["write"]()
console.log(arguments[2]);
}
foo( 1 , 2 , 3 , 4 , 5 , 6 , 7 );
4、函數的返回值-return(重點)
- 將函數執行處理的數據,返回出來,
- 便於其他程序或用戶調用或做二次使用
- 關鍵字 : return => 函數體內使用;
function foo(){
return "hello world";
}
console.log(foo());
// = > "hello world"
- return的特性
- 在函數之中,只要遇到了return關鍵字,表示函數執行結束,會立即跳出函數執行。
- 無論有多少個return ,只會執行第一個return,因為后面的就不執行了。
- 因此函數有一個特點, 返回值只能有一個;
function foo(){
return "hello world1";
return "hello world2";
return "hello world3";
}
console.log(foo());
// = > "hello world1"
- 函數的運算結果可以是什么樣的數據類型;
- return 可以返回什么數據類型那 ?
- 任意數據類型都可以返回;
**如果函數返回了一個函數會發生什么 ? **
function foo(){
console.log("foo");
function poo(){
console.log("poo")
}
return poo;
}
var res = foo();
// 此時 res 里面存儲的是 poo 函數的地址;
// 此時的 res 和 poo 完全一樣;
res();
5、函數的遞歸(重點)
- 一個函數調用了他自身,這種現象叫遞歸
注意
- 遞歸就是函數自己調用自己
- 遞歸類似於循環
- 遞歸函數要注意停止返回,否則會造成死遞歸
- 遞歸比較消耗性能,盡量少用
我們想要把遞歸進行正經的應用:
- 終止條件 => 包裹在if之中的 return;
- 運算條件 => 算法; => 極簡算法;
- 返回結果 => return ;
用遞歸做一個簡單的案例:
// num 求 1 ~ num 的累加 ;
// 累加 : 1 + 2 + 3 + 4 + 5 + 6 ....
var count = 0;
function sum( num ){
// count(查看運行次數)
count ++;
// 這個運算的起始值,歸到起始點;
// 終止條件(必須要有不然會照成死循環)
if( num === 1){
return 1;
}
// 運算條件
return sum( num - 1 ) + num;
}
// sum( 1 ); // 1;
// sum( 2 ); // sum(1) + 2; => 3;
// sum( 3 ); // sum(2) + 3; => 6;
var res = sum(100);
console.log( res );
console.log(count);