JavaScript探索:从两数之和学习伪数组、参数校验和记忆函数

如果让你写一个求两数之和的函数,你能确保你的函数能够没有一点破绽吗?今天我们将从两数之和开始,带你学习js中的伪数组、参数校验和记忆函数。

两数之和

现在让你写一个两数之和的函数,你可能会想,这有什么难的,那你的函数是不是和这样的差不多呢?

css 复制代码
function add(a,b){
    return a+b
}

看起来没什么问题对吧,但真的有那么简单吗?

如果我传三个数进去add(1,2,3),你要如何应对呢?

如果我传字符串进去add(1,i),你又该如何应对呢?

所以看起来没问题,但实际上问题很大。接下来一起看看这些问题要怎么解决吧!

伪数组arguments

在JavaScript中,arguments是一个特殊的对象,它包含了函数调用时传递的所有参数。它可以在函数内部使用,用于访问和操作传递给函数的参数。

arguments对象类似于一个数组,但它并不是一个真正的数组,而是一个类似数组的对象。它具有length属性来表示传递给函数的参数个数,并且可以通过索引访问每个参数的值。

以下是arguments对象的一些常见用法示例:

访问参数值:

javascript 复制代码
function myFunction(a, b) {
  console.log(arguments[0]); // 输出第一个参数的值
  console.log(arguments[1]); // 输出第二个参数的值
}
myFunction('Hello', 'World');
// 输出:
// Hello
// World

遍历参数:

javascript 复制代码
function myFunction() {
  for (var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
}
myFunction('Hello', 'World');
// 输出:
// Hello
// World

在两数之和问题中,如果我们要限定传进来的参数个数,可以借助arguments来实现:

javascript 复制代码
function add(a,b){
    if(arguments.length!=2){
        throw new Error('必须传递两个参数')//抛出错误,程序终止
    }
    return a+b
}

console.log(add(1,2,3));

参数传进来后,我们先用arguments.length来判断参数的数量是否是2,如果不是则抛出错误,这里我们使用throw new Error(),程序会立即终止。

如果你想要程序还能继续运行,可以用try{}catch(e){console.log(e);}:

javascript 复制代码
function add(a,b){
    if(arguments.length!=2){
        throw new Error('必须传递两个参数')
    }
    return a+b
}
try{   // 抛出错误,还能继续执行
    console.log(add(1,2,3));
}catch(e) {
    console.log(e);
}
console.log('continue...')

抛出错误后,还能继续执行之后的console.log('continue...')

使用arguments需要注意的是,arguments是一个伪数组,它没有数组的一些方法,如push()或pop(),也不能使用join()。如果需要使用数组的方法,可以将arguments对象转换为真正的数组 ,例如使用Array.from(arguments)[...arguments]

参数校验

解决了参数数量问题,我们再来看如何解决参数的数据类型问题。

在JavaScript中参数校验是指对函数或方法的输入参数进行验证和检查的过程。它旨在确保传递给函数的参数满足预期的条件和要求,从而提高代码的可靠性和安全性。

这里我们进行数据类型验证:检查参数的数据类型是否符合预期,如数字、字符串、数组等。

要得到参数的数据类型是什么,我们可以使用typeof

javascript 复制代码
if(typeof a !== 'number' || typeof b !== 'number'){
    throw new Error('必须是整数');
}

如果两个参数中部全是整数,则抛出错误。

现在,这个函数就已经变得很完美啦!

javascript 复制代码
function add(a,b) {
    if(arguments.length !== 2){
        throw new Error('传递的参数个数有误');
    }
    if(typeof a !== 'number' || typeof b !== 'number'){
        throw new Error('必须是整数');
    }
    return a+b
}

记忆函数

上面的add函数,如果我们多次调用它,但每次传进去的参数都是相同的,那它就会重复做很多相同的运算,那么有没有办法能够减少它的重复运算,提高效率,让它更完美呢?当当~这个时候就轮到记忆函数出场了!

在JavaScript中,记忆函数(Memoization Function)是一种优化技术,用于缓存函数的计算结果,以避免重复计算相同的输入值。记忆函数可以显著提高函数的性能,尤其是对于那些计算量较大、耗时较长的函数。

记忆函数的核心思想是将函数的输入值与其对应的输出结果保存在一个缓存对象中。当函数被调用时,首先检查缓存中是否已经有了该输入值的计算结果,如果有,则直接返回缓存中的结果,而不需要重新执行函数体。如果缓存中没有对应的结果,则执行函数体计算结果,并将计算结果存入缓存中供下次使用。

javascript 复制代码
function add(a,b) {
    if(arguments.length !== 2){
        throw new Error('传递的参数有误');
    }
    if(typeof a !== 'number' || typeof b !== 'number'){
        throw new Error('必须是整数');
    }
    return a+b
}
// 记忆函数 
function memorize(f){
    if(typeof f !== 'function') return;
    var cache = {} //缓存空间
    return function(){
        var key = arguments.length + Array.prototype.join.call(arguments,',')
        if(key in cache){  // 如果缓存中已有结果,则直接返回
            return cache[key]
        }else{
             // 执行函数体计算结果
            return cache[key] = f.apply(this,arguments)
        }
    }
}

const memorizedAdd = memorize(add);
console.log(memorizedAdd(1,2));//通过add计算出值
console.log(memorizedAdd(1,2));//从cache中取值不用再调用add计算

第一遍计算的输入值与输出结果会保存在cache中,如果之后有相同的输入则直接取值不用再计算了,若没有则进行计算并存入cache中。

这次的知识点已经讲完啦!欢迎下次再来一起学习哦ヾ(◍°∇°◍)ノ゙

相关推荐
来自星星的坤1 小时前
【Vue 3 + Vue Router 4】如何正确重置路由实例(resetRouter)——避免“VueRouter is not defined”错误
前端·javascript·vue.js
香蕉可乐荷包蛋5 小时前
浅入ES5、ES6(ES2015)、ES2023(ES14)版本对比,及使用建议---ES6就够用(个人觉得)
前端·javascript·es6
未来之窗软件服务6 小时前
资源管理器必要性———仙盟创梦IDE
前端·javascript·ide·仙盟创梦ide
liuyang___7 小时前
第一次经历项目上线
前端·typescript
西哥写代码7 小时前
基于cornerstone3D的dicom影像浏览器 第十八章 自定义序列自动播放条
前端·javascript·vue
清风细雨_林木木7 小时前
Vue 中生成源码映射文件,配置 map
前端·javascript·vue.js
FungLeo8 小时前
node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示
前端·非对称加密·rsa 加密·node 后端
雪芽蓝域zzs8 小时前
JavaScript splice() 方法
开发语言·javascript·ecmascript
不灭锦鲤8 小时前
xss-labs靶场第11-14关基础详解
前端·xss
不是吧这都有重名8 小时前
利用systemd启动部署在服务器上的web应用
运维·服务器·前端