与函数相关(含递归、深克隆、sort方法)

什么是函数

  • 函数就是语句(功能)的封装,可以让这些代码方便地被复用;
  • 函数具有“一次定义,多次调用”的优点;
  • 使用函数,可以简化代码,让代码更具有可读性;

函数的定义

  • 和变量类似,函数必须先定义然后才能使用
  • 使用function关键字定义函数,function是“功能”的意思
function name(params) {
    // 函数体语句
}
// 匿名函数
var fun = function (params) {
    // 函数体语句            
}

函数的调用

  • 执行函数体中的所有语句,就称为“调用函数”;
  • 函数必须要调用才能够执行;
fun()  //调用函数

函数声明的提升

fun();  // 函数被执行
function fun() {
    console.log('函数被执行');
}

函数表达式不能提升

如果函数使用函数表达式的写法定义的,则没有提升的特性

fun();  // 引发错误: Uncaught TypeError: fun is not a function
var fun = function () {
    console.log('函数被执行');
}

函数的参数

  • 参数是函数内的一些待定值,在调用函数时,必须传入这些参数的具体值
  • 函数的参数可多可少,函数可以没有参数,也可以有多个参数,多个参数之间需要用逗号隔开;

arguments

函数内arguments表示它接收到的实参列表,它是一个类数组对象

类数组对象:所有属性均为从0开始的自然数序列,并且有length属性,和数组类似可以用方括号书写下标访问对象的某个属性值,但是不能调用数组的方法;

function fun() {
    console.log(arguments);  // Arguments(4) [11, 1, 2, 45, callee: ƒ, Symbol(Symbol.iterator): ƒ]
    console.log(arguments[0]);  // 11
    console.log(arguments[1]);  // 1
}
fun(11,1,2,45);

// 不管用户传入多少个实际参数,永远能够计算它们的和
function fun2() {
    var sum = 0;
    for(var i = 0; i < arguments.length; i++){
        sum += arguments[i];
    }
    console.log('所有参数的和是' + sum);   // 所有参数的和是12
}
fun2(1,2,3,6)

函数的返回值

  • 函数体内可以使用return关键字表示“函数的返回值”
// 函数的功能是返回两个参数的和
function sum(a, b) {
    return a + b;
}
var result = sum(3,5);
console.log('两个数字的和是'+result);
  • 调用一个有返回值的函数,可以被当做一个普通值,从而可以出现在任何可以书写值的地方
function sum(a, b) {
    return a + b;
}
var result = sum(3,5) * sum(4,2);
console.log(result);  // 48

function sum(a, b) {
    return a + b;
}
var result = sum(3,sum(4,2));
console.log(result);  // 9
  • 调用函数时,一旦遇见return语句则会立即退出函数,将执行权交还给调用者;
function fun() {
    console.log(1);
    return 2;
    console.log(3);
}
console.log(4)
var char = fun();
console.log(char);
console.log(5);

内置sort()方法

数组排序可以使用sort()方法,这个方法的参数又是一个函数;

这个函数中的a、b分别表示数组中靠前和靠后的项,如果需要将它们交换位置,则返回任意正数;否则就返回负数;

var arr = [33,552,11,44];
arr.sort(function (a,b) {
    if (a>b) {
        return 1;
    } else {
        return -1;
    }
})
console.log(arr);  // (4) [11, 33, 44, 552]

递归

函数的内部语句可以调用这个函数自身,从而发起对函数的一次迭代。在新的迭代中,又会执行调用函数自身的语句,从而又产生一次迭代。当函数执行到某一次时,不再进行新的迭代,函数被一层一层返回,函数被递归;

递归的要素

边界条件:确定递归到何时终止,也称为递归出口;

递归模式:大问题是如何分解为小问题的,也称为递归体

// 斐波那契数列
// 编写一个函数,这个函数的功能是返回斐波那契数列中下标为n的那项的值
function fib(n) {
    // 数列的下标为0和1的项的值是1
    if (n==0 || n==1) return 1;
    // 斐波那契数列的本质特征就是每一项都等于前面两项的和
    return fib(n-1) + fib(n - 2);
}
// console.log(fib(6));
// 书写一个循环语句,计算斐波那契数列的前15项
for(var i = 0; i < 15; i++){
    console.log(fib(i));
}

实现深克隆

使用递归思想;如果遍历到项是基本类型值,则直接推入结果数组;如果遍历到的项是数组,则重复执行浅克隆的操作;

// 复习浅克隆
var arr = [11,22,55,66,3,[1,2]];
var result = [];
for (var i = 0; i < arr.length; i++) {
    result.push(arr[i]);
}
// 输出结果数组
console.log(result);
// 测试是否实现了克隆,就是说本质上是内存中的不同数组了
console.log(arr == result);
// 测试这样的克隆是浅克隆,“藕断丝连”
arr[5].push(9);
console.log(result);

// 深克隆
// 原数组
var arr1 = [1,2,3,4,[5,8,[5,9]]];
// 函数,这个函数会被递归
function deepClone(arr) {
    // 结果数组;定义在里面是因为,他是一个局部变量,每次遍历的时候都要重新生产
    // “每一层”都会有一个结果数组
    var result = [];
    // 遍历数组的每一项
    for(var i = 0; i < arr.length; i++){
        // 类型判断,如果遍历到的项是数组
        if (Array.isArray(arr[i])) {
            // 递归
            result.push(deepClone(arr[i]));
        }else{
            // 如果遍历到的项不是数组,是基本类型值,就直接推入到结果数组中
            // 相当于是递归的出口
            result.push(arr[i]);
        }
    }
    // 返回结果数组
    return result;
}
// 测试一下
var arr2 = deepClone(arr1);
console.log(arr2);  // (5) [1, 2, 3, 4, Array(3)]
// 是否藕断丝连;否
console.log(arr1[4] == arr2[4]);  // false
arr1[4].push(99);
arr1[4][2].push(19);
console.log(arr1[4])  // (4) [5, 8, Array(3), 99]
console.log(arr2[4]);  // (3) [5, 8, Array(2)]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值