一、函数的实参集合-arguments

  • 现在有个需求,需要写一个方法,求10数的和。

代码如下:

  1. function sum(a, b, c, d, e, f, g, h, i, j) {
  2. var total = a + b + c + d + e + f + g + h + i + j;
  3. return total;
  4. }
  5. sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

函数形参的局限性:

  1. 因为形参和实参是一一对应的,如果想要多少传递多少实参,就要设置多少形参,这很不方便,现在是10个,如果是100个,就要设置100个形参。
  2. 如果实参个数不固定,可能10个可能2个,还可能100个,所以此时形参无法设置。
  • 需求2:需要写一个方法,实现可以求任意多个数字之和;

任意多个实参,此时形参不固定了。怎么办?

为了解决上面的形参的种种限制,浏览器为函数内置一个 arguments 对象; arguments:arguments 叫做内置的实参集合,这个对象里面包含了函数执行时传递进来的所有实参(内置:函数天生自带的机制,不管是否设置了形参,也不管你是否传递了实参,arguments 一直都存在)。

使用 arguments:

  1. function sum2(n, m) {
  2. console.log(n, m);
  3. console.log(arguments);
  4. arguments 它是一个类数组(不是数组,不能直接使用数组中的方法)
  5. 即使设置形参变量,形参该是什么还是什么,但是 arguments 存储的是所有传进来的实参,所以 arguments 被称为 实参集合
  6. 我们发现它有索引,有 length,可以用 for 循环遍历
  7. {
  8. 0: 1,
  9. 1: 2,
  10. 2: 5,
  11. 3: 7,
  12. 4: 8
  13. length: 5,
  14. callee: 存储的当前函数本身 arguments.callee == sum2 -> true
  15. }
  16. }
  17. sum2(1, 2, 5, 7, 8);

ES6 不定参数

  • ES6中提供了一个功能和 arguments 的功能相似的功能———— 不定参数

    1. function sum(...arg) {
    2. // ...叫做展开运算符
    3. // arg 是一个形参变量
    4. console.log(arg); arg 是一个数组
    5. }
    6. sum(1, 2, 4, 5, 7);
  • arguments 和 不定参数的不同

  1. arguments 是函数天生自带的属性不需要声明,而不定参数需要声明
  2. arguments 是类数组,而不定参数是数组

任意数求和:
思路:

  1. 既然是任意数,那么肯定使用函数的 arguments
  2. arguments 里面存储着所有的实参,我们需要把这些实参一个一个的取出来(遍历),然后加给一个基础值上
  3. 把结果 return 出去

    基础版:

  1. function sum3() {
  2. // 1. 设立初始值
  3. var total = 0;
  4. // 2. 遍历arguments
  5. for (var i = 0; i < arguments.length;i++) {
  6. var item = arguments[i];
  7. total += item;
  8. }
  9. // 3. 把计算结果返回
  10. return total;
  11. }
  12. var result = sum3(1, 2, 4, 5);
  13. console.log(result);

升级版:为了提高代码的健壮性,我们累加的时候需要判断一下我们传进来的实参是不是一个数字,如果不是数字,我们先给它转成数字,然后再看转换后是不是有效数字,如果是再加,如果不是就不加了。

  1. function sum4() {
  2. // 1. 设立初始值
  3. var total = 0;
  4. // 2. 遍历 arguments 对象,取出每一项
  5. for (var i = 0; i < arguments.length; i++) {
  6. // 3. 不管你传进来的是不是数字,都转一次
  7. var item = Number(arguments[i]);
  8. // 4. 判断转换后的结果是不是有效数字累加,非有效数字直接跳过
  9. if (!isNaN(item)) {
  10. // 如果不是 NaN 就让 total 加等于 item
  11. total += item;
  12. }
  13. }
  14. return total;
  15. }
  16. console.log(sum4(10, '20', 'aa')); // 30

二、函数表达式

  • 函数分类:
  1. 实名函数:有函数名的
  2. 匿名函数:没有函数名的
    2.1 函数表达式:把函数当做赋值给变量或者元素对象的事件属性
    2.2 自执行函数:创建和执行一起完成的
  • 函数表达式:
  1. 把函数当成一个值赋值给变量或者对象的属性 ```javascript var fn = function () { console.log(‘我是一个函数表达式’); }; fn(); // fn 是一个变量名,它代表的也是一个函数

    赋值给元素对象的事件属性: oBox.onclick = function () {};

    普通对象的属性值:

var obj = { getName: function () { console.log(‘珠峰培训’) } } obj.getName(); // 因为 obj.getName 是一个函数,因此也可以执行

  1. 2. 自执行函数:函数的定义和声明都放在一起了
  2. ```javascript
  3. (function (i) {
  4. 第一部分是函数定义
  5. console.log('i 是', i);
  6. })(10); 后面的小括号放在函数后面就是让函数执行的
  7. 以下都是自执行函数
  8. ~function (i) {
  9. console.log(i);
  10. }(10);
  11. +function (i) {
  12. console.log(i);
  13. }(10);
  14. !function (i) {
  15. console.log(i);
  16. }(10);

三、函数递归

函数:分为定义部分和执行部分

函数递归(recursion):在函数体内部,调用函数自身,达到重复某一行为的目的。

  • 需求:写一个方法求出 1-10之间所有数的数字之和
  1. function rSum(num) {
  2. if (num === 10) {
  3. return 10
  4. }
  5. return num + rSum(num + 1)
  6. // 如果函数的返回值遇到一个表达式,那么函数会等着这个表达式求值完成最后把这个值返回出去。
  7. // return 1 + rSum(2)
  8. // return 1 + 2 + rSum(3)
  9. // return 1 + 2 + 3 + rSum(4)
  10. // return 1 + 2 + 3 + 4 + rSum(5)
  11. // return 1 + 2 + 3 + 4 + 5 + rSum(6)
  12. // return 1 + 2 + 3 + 4 + 5 + 6 + rSum(7)
  13. // return 1 + 2 + 3 + 4 + 5 + 6 + 7 + rSum(8)
  14. // return 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + rSum(9)
  15. // return 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + rSum(10)
  16. // return 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
  17. }
  18. console.log(rSum(1));
  • 需求:求1-10中的是3的倍数的所有数之和。
    1. function rSum2(num) {
    2. if (num === 10) {
    3. return 0
    4. }
    5. if (num % 3 === 0) {
    6. return num + rSum2(num + 1)
    7. } else {
    8. return rSum2(num + 1);
    9. }
    10. // return rSum2(2)
    11. // return rSum2(3)
    12. // return 3 + rSum2(4)
    13. // return 3 + rSum2(5)
    14. // return 3 + rSum2(6)
    15. // return 3 + 6 + rSum2(7)
    16. // return 3 + 6 + rSum2(8)
    17. // return 3 + 6 + rSum2(9)
    18. // return 3 + 6 + 9 + rSum(10)
    19. // return 3 + 6 + 9 + 0
    20. }
    21. console.log(rSum2(1));

注意:递归和for循环一样,在使用时考虑好递归终止的条件。不然就会造成死循环,导致栈内存溢出(stack overflow)


四、数组常用方法

I. 数组的删除和追加

  1. => push
  • 作用:向数组末尾追加项(可以多项,多项直接用逗号分隔)
  • 参数:需要添加到数组的项
  • 返回值:数组追加项之后的长度
  • 原数组是否改变:是
    1. var ary1 = [1, 2, 3];
    2. var r1 = ary1.push(4, 5);
    3. console.log(ary1, r1);
  1. => pop
  • 作用:删除数组末尾一项
  • 参数:无
  • 返回值:被删除的数组项
  • 原数组是否改变:是
  1. var ary2 = [1, 2, 4];
  2. var r2 = ary2.pop();
  3. console.log(ary2, r2);
  1. => unshift
  • 作用:向数组开头添加项
  • 参数:需要追加到开头的项
  • 返回值:追加完内容后的数组新长度
  • 原数组是否改变:是
  1. var ary3 = [1, 2, 3];
  2. var r3 = ary3.unshift(4, 5);
  3. console.log(ary3, r3);
  1. => shift
  • 作用:删除数组起始一项
  • 参数:无
  • 返回值:被删除的项
  • 原数组是否改变:是
  1. var ary4 = [1, 2, 3];
  2. var r4 = ary4.shift();
  3. console.log(ary4, r4);
  1. => splice(n, m)
  • 作用:从索引为 n 开始删除 m 个
  • 参数:起始索引 n,要删除的个数
  • 返回值:由删除的项组成新数组
  • 原数组是否改变:是
  1. var ary5 = [1, 2, 3];
  2. var r5 = ary.splice(1, 2);
  3. console.log(ary5, r5);
  1. => splice(n, m, x)
  • 作用:从索引 n 开始删除 m 个,用 x 替换删除的部分
  • 参数:起始索引,删除个数,用来替换的数组项x
  • 返回值:被删除的项组成的新数组
  • 原数组是否改变:是
  1. var ary6 = [1, 2, 3];
  2. var r6 = ary.splice(1, 1, 5);
  3. console.log(ary6, r6);
  1. => splice(n, 0, x)
  • 作用:从索引n开始删除0个,把x插入到n的前面
  • 参数:起始索引,删除个数0,x
  • 返回值:空数组
  • 原数组是否改变:是
  1. var r7 = ary.splice(1, 0, 5);
  2. var ary7 = [1, 2, 3];
  3. console.log(ary7, r7);
  • II. 数组复制、拼接
  1. slice(n, m)
  • 作用:从索引 n 开始复制到索引 m(不包括m)
  • 参数:起始索引 n,终点索引 m; 注意:m 不写就是复制到最后一项,如果 n 和 m 都不写也是从开头复制到末尾
  • 返回值:复制的项组成的新数组
  • 原数组是否改变:否
  1. var ary8 = [1, 2, 4, 5];
  2. var r8 = ary8.slice(1, 3);
  3. var r9 = ary8.slice(1);
  4. var r10 = ary8.slice();
  5. var r11 = ary.slice(0);
  6. console.log(r8);
  7. console.log(r9);
  8. console.log(r10);
  9. console.log(r11);
  1. => concat()
  • 作用:将数组拼接起来
  • 参数:需要拼接的数组或者数组项
  • 返回值:拼接过后的新数组
  • 原数组是否改变:否
  1. var ary12 = [1, 3, 5, 7];
  2. var r12 = ary12.concat([9, 11]); // 参数传递一个数组
  3. console.log(ary12, r12);
  4. var r13 = ary12.concat(9, 11); // 参数传递数组项
  5. console.log(ary12, r13);
  6. var r14 = ary12.concat(); // 一个参数不传相当于把数组复制一份
  7. console.log(r14);
  8. console.log(r14 === ary12); // false

III. 数组的转换成字符串

  1. => join()
  • 作用:根据参数指定的分隔符把数组连接成字符串
  • 参数:分隔符,不指定时默认空字符串
  • 返回值:拼接过后的字符串
  • 原数组是否改变:否
    1. var ary15 = [1, 3, 5, 7];
    2. var str15 = ary15.join('+');
    3. console.log(ary15, str15);
  1. => toString()
  • 作用:把数组转换成字符串
  • 参数:无
  • 返回值:字符串
  • 原数组是否改变:否
    1. var ary16 = [1, 2, 5, 8];
    2. var str16 = ary16.toString();
    3. console.log(ary16, str16);

IV 数组项是否在数组中出现过

  1. => indexOf(x)
  • 作用:数组项 x 在数组中第一次出现的索引位置
  • 参数:数组项x
  • 返回值:如果数组中存在该项,就返回该项第一次出现的索引,如果不存在,则返回 -1
  • 原数组是否改变:否 ```javascript 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. 2. => lastIndexOf(x)
  2. - 作用:数组项 x 在数组中最后一次出现的索引位置
  3. - 参数:数组项x
  4. - 返回值:如果数组中存在该项,就返回该项最后一次出现的索引,如果不存在,则返回 -1
  5. - 原数组是否改变:否
  6. ```javascript
  7. var ary19 = [1, 3, 5, 7, 3];
  8. var r19 = ary19.lastIndexOf(3);
  9. console.log(ary19, r19);
  10. var r20 = ary19.lastIndexOf('bingo');
  11. console.log(ary19, r20); // -1

V. 数组排序和倒序

  1. => sort(function (a, b) {
    return a - b
    })
  • 作用:给数组按照升序或者降序排列
  • 参数:回调函数
  • 返回值:如果回调函数 return a - b 就返回升序排列后的数组
  • 如果回调函数 return b - a,返回降序排列后的数组;
  • 原数组是否改变:是
    1. var ary21 = [1, 5, 2, 6, 4];
    2. var r21 = ary21.sort(function (a, b) {
    3. return a - b
    4. });
    5. var r22 = ary21.sort(function (a, b) {
    6. return b - a;
    7. });
    8. console.log(ary21, r21, r22);
  1. reverse()
  • 作用:让数组翻转过来排列
  • 参数:无
  • 返回值:翻转过后的数组
  • 原数组是否改变:是
    1. var re = ary21.reverse();
    2. console.log(ary21, re);

VI 数组的遍历方法(遍历:就是把数组里面的每一项都取出来)

  1. forEach(function (item, index) {
    在回调函数里可以操作这些值
    })
  • 作用:遍历数组
  • 参数:回调函数(回调函数的参数:item 是遍历时每一个数组项,index 是这个数组项的索引)
  • 返回值:无
  • 原数组是否改变:否 ```javascript var ary23 = [1, 2, 5, 7, 9];

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

  1. 2. => map(function (item, index) {})
  2. - 作用:将原数组映射成一个新数组
  3. - 参数:回调函数(回调函数的参数同 forEach
  4. - 返回值:由回调函数的返回值组成的新数组
  5. - 原数组是否改变:否
  6. ```javascript
  7. var ary24 = [1, 2, 5];
  8. var r24 = ary24.map(function (item, index) {
  9. return item * 2;
  10. });
  11. console.log(ary24, r24);