基礎教程 5. arguments、遞歸和函數表達式

這是我參與8月更文挑戰的第4天,活動詳情查看:8月更文挑戰javascript

1、函數的實參集合-arguments

  • 如今有個需求,須要寫一個方法,求10數的和。

代碼以下:html

function sum(a, b, c, d, e, f, g, h, i, j) {
  var total = a + b + c + d + e + f + g + h + i + j;
  return total;
}

sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
複製代碼

函數形參的侷限性:java

  1. 由於形參和實參是一一對應的,若是想要多少傳遞多少實參,就要設置多少形參,這很不方便,如今是10個,若是是100個,就要設置100個形參。
  2. 若是實參個數不固定,可能10個可能2個,還可能100個,因此此時形參沒法設置。
  • 需求2:須要寫一個方法,實現能夠求任意多個數字之和;

任意多個實參,此時形參不固定了。咋辦?數組

爲了解決上面的形參的種種限制,瀏覽器爲函數內置一個arguments對象;瀏覽器

arguments:arguments叫作內置的實參集合,這個對象裏面包含了函數執行時傳遞進來的全部實參(內置:函數天生自帶的機制,不論是否設置了形參,也無論你是否傳遞了實參,arguments一直都存在)。markdown

使用arguments:函數

function sum2(n, m) {
  console.log(n, m);
  console.log(arguments);

   arguments它是一個類數組(不是數組,不能直接使用數組中的方法)
   即便設置形參變量,形參該是什麼仍是什麼,可是arguments存儲的是全部傳進來的實參,因此arguments被稱爲 實參集合
   咱們發現它有索引,有length,能夠用for循環遍歷
   {
     0: 1,
     1: 2,
     2: 5,
     3: 7,
     4: 8
     length: 5,
     callee: 存儲的當前函數自己 arguments.callee == sum2 -> true
    }



}

sum2(1, 2, 5, 7, 8);
複製代碼

ES6 不定參數

  • ES6中提供了一個功能和arguments的功能類似的功能——不定參數
function sum(...arg) {
   ...叫作展開運算符
   arg 是一個形參變量
  console.log(arg);  arg是一個數組
}
sum(1, 2, 4, 5, 7);
複製代碼
  • arguments 和 不定參數的不一樣
  1. arguments是函數天生自帶的屬性不須要聲明,而不定參數須要聲明
  2. arguments是類數組,而不定參數是數組

任意數求和:

思路:post

  1. 既然是任意數,那麼確定使用函數的arguments
  2. arguments裏面存儲着全部的實參,咱們須要把這些實參一個一個的取出來(遍歷),而後加給一個基礎值上
  3. 把結果return出去

基礎版:ui

function sum3() {
   1. 設立初始值
  var total = 0;

   2. 遍歷arguments
  for (var i = 0; i < arguments.length;i++) {
    var item = arguments[i];
    total += item;
  }
   3. 把計算結果返回
  return total;
}

var result = sum3(1, 2, 4, 5);
console.log(result);
複製代碼

升級版:爲了提升代碼的健壯性,咱們累加的時候須要判斷一下咱們傳進來的實參是否是一個數字,若是不是數字,咱們先給它轉成數字,而後再看轉換後是否是有效數字,若是是再加,若是不是就不加了。spa

function sum4() {
   1. 設立初始值
  var total = 0;
   2. 遍歷arguments對象,取出每一項
  for (var i = 0; i < arguments.length; i++) {
     3. 無論你傳進來的是否是數字,都轉一次
    var item = Number(arguments[i]);
     4. 判斷轉換後的結果是否是有效數字累加,非有效數字直接跳過
    if (!isNaN(item)) {
       若是不是NaN就讓total加等於item
      total += item;
    }
  }
  return total;
}
console.log(sum4(10, '20', 'aa'));  30

複製代碼

2、函數表達式

  • 函數分類:
  1. 實名函數:有函數名的
  2. 匿名函數:沒有函數名的

2.1 函數表達式:把函數當作賦值給變量或者元素對象的事件屬性 2.2 自執行函數:建立和執行一塊兒完成的

  • 函數表達式:
  1. 把函數當成一個值賦值給變量或者對象的屬性
var fn = function () {
  console.log('我是一個函數表達式');
};
fn();  fn是一個變量名,它表明的也是一個函數

 賦值給元素對象的事件屬性:
oBox.onclick = function () {};

 普通對象的屬性值:

var obj = {
  getName: function () {
    console.log('江外琉璃')
  }
}
obj.getName();  由於obj.getName 是一個函數,所以也能夠執行
複製代碼
  1. 自執行函數:函數的定義和聲明都放在一塊兒了
(function (i) {
   第一部分是函數定義
  console.log('i 是', i);
})(10); 後面的小括號放在函數後面就是讓函數執行的

 如下都是自執行函數
~function (i) {
  console.log(i);
}(10);

+function (i) {
  console.log(i);
}(10);

!function (i) {
  console.log(i);
}(10);
複製代碼

3、函數遞歸

函數:分爲定義部分和執行部分

函數遞歸(recursion):在函數體內部,調用函數自身,達到重複某一行爲的目的。

  • 需求:寫一個方法求出 1-10之間全部數的數字之和
function rSum(num) {
  if (num === 10) {
    return 10
  }
  return num + rSum(num + 1)
   若是函數的返回值遇到一個表達式,那麼函數會等着這個表達式求值完成最後把這個值返回出去。
   return 1 + rSum(2)
   return 1 + 2 + rSum(3)
   return 1 + 2 + 3 + rSum(4)
   return 1 + 2 + 3 + 4 + rSum(5)
   return 1 + 2 + 3 + 4 + 5 + rSum(6)
   return 1 + 2 + 3 + 4 + 5 + 6 + rSum(7)
   return 1 + 2 + 3 + 4 + 5 + 6 + 7 + rSum(8)
   return 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + rSum(9)
   return 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + rSum(10)
   return 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
}
console.log(rSum(1));
複製代碼
  • 需求:求1-10中的是3的倍數的全部數之和。
function rSum2(num) {
  if (num === 10) {
    return 0
  }
  if (num % 3 === 0) {
    return num + rSum2(num + 1)
  } else {
    return rSum2(num + 1);
  }
   return rSum2(2)
   return rSum2(3)
   return 3 + rSum2(4)
   return 3 + rSum2(5)
   return 3 + rSum2(6)
   return 3 + 6 + rSum2(7)
   return 3 + 6 + rSum2(8)
   return 3 + 6 + rSum2(9)
   return 3 + 6 + 9 + rSum(10)
   return 3 + 6 + 9 + 0
}
console.log(rSum2(1));
複製代碼

注意:遞歸和for循環同樣,在使用時考慮好遞歸終止的條件。否則就會形成死循環,致使棧內存溢出(stack overflow)

4、數組經常使用方法

I 數組的刪除和追加

  1. => push
  • 做用:向數組末尾追加項(能夠多項,多項直接用逗號分隔)
  • 參數:須要添加到數組的項
  • 返回值:數組追加項以後的長度
  • 原數組是否改變:是
var ary1 = [1, 2, 3];
var r1 = ary1.push(4, 5);
console.log(ary1, r1);
複製代碼
  1. => pop
  • 做用:刪除數組末尾一項
  • 參數:無
  • 返回值:被刪除的數組項
  • 原數組是否改變:是
var ary2 = [1, 2, 4];
var r2 = ary2.pop();
console.log(ary2, r2);
複製代碼
  1. => unshift
  • 做用:向數組開頭添加項
  • 參數:須要追加到開頭的項
  • 返回值:追加完內容後的數組新長度
  • 原數組是否改變:是
var ary3 = [1, 2, 3];
var r3 = ary3.unshift(4, 5);
console.log(ary3, r3);
複製代碼
  1. => shift
  • 做用:刪除數組起始一項
  • 參數:無
  • 返回值:被刪除的項
  • 原數組是否改變:是
var ary4 = [1, 2, 3];
var r4 = ary4.shift();
console.log(ary4, r4);
複製代碼
  1. => splice(n, m)
  • 做用:從索引爲n開始刪除m個
  • 參數:起始索引n,要刪除的個數
  • 返回值:由刪除的項組成新數組
  • 原數組是否改變:是
var ary5 = [1, 2, 3];
var r5 = ary.splice(1, 2);
console.log(ary5, r5);
複製代碼
  1. => splice(n, m, x)
  • 做用:從索引n開始刪除m個,用x替換刪除的部分
  • 參數:起始索引,刪除個數,用來替換的數組項x
  • 返回值:被刪除的項組成的新數組
  • 原數組是否改變:是
var ary6 = [1, 2, 3];
var r6 = ary6.splice(1, 1, 5);
console.log(ary6, r6);

複製代碼
  1. => splice(n, 0, x)
  • 做用:從索引n開始刪除0個,把x插入到n的前面
  • 參數:起始索引,刪除個數0,x
  • 返回值:空數組
  • 原數組是否改變:是
var r7 = ary.splice(1, 0, 5);
var ary7 = [1, 2, 3];
console.log(ary7, r7);

複製代碼

II. 數組複製、拼接

  1. slice(n, m)
  • 做用:從索引n開始複製到索引m(不包括m)
  • 參數:起始索引n,終點索引m; 注意:m不寫就是複製到最後一項,若是n和m都不寫也是從開頭複製到末尾
  • 返回值:複製的項組成的新數組
  • 原數組是否改變:否
var ary8 = [1, 2, 4, 5];
var r8 = ary8.slice(1, 3);
var r9 = ary8.slice(1);
var r10 = ary8.slice();
var r11 = ary.slice(0);
console.log(r8);
console.log(r9);
console.log(r10);
console.log(r11);

複製代碼
  1. => concat()
  • 做用:將數組拼接起來
  • 參數:須要拼接的數組或者數組項
  • 返回值:拼接事後的新數組
  • 原數組是否改變:否
var ary12 = [1, 3, 5, 7];
var r12 = ary12.concat([9, 11]);  參數傳遞一個數組
console.log(ary12, r12);

var r13 = ary12.concat(9, 11);  參數傳遞數組項
console.log(ary12, r13);

var r14 = ary12.concat();  一個參數不傳至關於把數組複製一份
console.log(r14);
console.log(r14 === ary12);  false

複製代碼

III. 數組的轉換成字符串

  1. => join()
  • 做用:根據參數指定的分隔符把數組連接成字符串
  • 參數:分隔符,不指定時默認空字符串
  • 返回值:拼接事後的字符串
  • 原數組是否改變:否
var ary15 = [1, 3, 5, 7];
var str15 = ary15.join('+');
console.log(ary15, str15);

複製代碼
  1. => toString()
  • 做用:把數組轉換成字符串
  • 參數:無
  • 返回值:字符串
  • 原數組是否改變:否
var ary16 = [1, 2, 5, 8];
var str16 = ary16.toString();
console.log(ary16, str16);

複製代碼

IV 數組項是否在數組中出現過

  1. => indexOf(x)
  • 做用:數組項x在數組中第一次出現的索引位置
  • 參數:數組項x
  • 返回值:若是數組中存在該項,就返回該項第一次出現的索引,若是不存在,則返回 -1
  • 原數組是否改變:否
var ary17 = [1, 3, 5, 7];
var r17 = ary17.indexOf(3);
console.log(ary17, r17);

var r18= ary17.indexOf('bingo');
console.log(ary17, r18);  -1
複製代碼
  1. => lastIndexOf(x)
  • 做用:數組項x在數組中最後一次出現的索引位置
  • 參數:數組項x
  • 返回值:若是數組中存在該項,就返回該項最後一次出現的索引,若是不存在,則返回 -1
  • 原數組是否改變:否
var ary19 = [1, 3, 5, 7, 3];
var r19 = ary19.lastIndexOf(3);
console.log(ary19, r19);

var r20 = ary19.lastIndexOf('bingo');
console.log(ary19, r20);  -1

複製代碼

V. 數組排序和倒序

  1. => sort(function (a, b) { return a - b

})

  • 做用:給數組按照升序或者降序排列
  • 參數:回調函數
  • 返回值:若是回調函數return a - b 就返回升序排列後的數組
  • 若是回調函數return b - a,返回降序排列後的數組;
  • 原數組是否改變:是
var ary21 = [1, 5, 2, 6, 4];
var r21 = ary21.sort(function (a, b) {
  return a - b
});
var r22 = ary21.sort(function (a, b) {
  return b - a;
});
console.log(ary21, r21, r22);

複製代碼
  1. reverse()
  • 做用:讓數組翻轉過來排列
  • 參數:無
  • 返回值:翻轉事後的數組
  • 原數組是否改變:是
var re = ary21.reverse();
console.log(ary21, re);

複製代碼

VI 數組的遍歷方法(遍歷:就是把數組裏面的每一項都取出來)

    1. forEach(function (item, index) {
    在回調函數裏能夠操做這些值

})

  • 做用:遍歷數組
  • 參數:回調函數(回調函數的參數:item是遍歷時每個數組項,index是這個數組項的索引)
  • 返回值:無
  • 原數組是否改變:否
var ary23 = [1, 2, 5, 7, 9];

var r23 = ary23.forEach(function (item, index) {
  console.log(item, index);
});
console.log(ary23, r23);

複製代碼
  1. => map(function (item, index) {})
  • 做用:將原數組映射成一個新數組
  • 參數:回調函數(回調函數的參數同forEach)
  • 返回值:由回調函數的返回值組成的新數組
  • 原數組是否改變:否
var ary24 = [1, 2, 5];
var r24 = ary24.map(function (item, index) {
  return item  2;
});
console.log(ary24, r24);
複製代碼
相關文章
相關標籤/搜索