js高级解法:记忆函数优化两数相加和递归(内含伪数组Arguments)

前言:

在日常的JavaScript编程中,经常会遇到需要计算两个数的和的场景。虽然最简单直接的方法是使用加法运算符直接相加,但对于大量重复计算的情况,这种方法可能会导致性能问题。为了解决这个问题,我们可以使用记忆函数来优化计算过程,避免重复计算,提高代码的执行效率。

记忆函数的原理:

记忆函数是一种将函数的计算结果缓存起来的技术。当函数被调用时,它首先检查之前是否已经计算过相同的输入,并将结果返回,而不是重新计算。这样可以避免重复计算,提高函数的执行效率。

记忆函数的实现:

在JavaScript中,我们可以使用闭包来实现记忆函数。具体步骤如下:

  1. 创建一个空对象,用于存储计算结果的缓存。
  2. 创建一个闭包函数,该函数接受两个参数作为输入。
  3. 在闭包函数内部,首先检查缓存对象中是否已经存在相同的输入作为键的计算结果。如果存在,则直接返回缓存中的结果。
  4. 如果缓存中不存在该输入的计算结果,则进行实际的计算,并将结果存储在缓存对象中。
  5. 最后,返回计算结果。

伪数组 Arguments

伪数组(pseudo-array)是指具有类似数组特性的对象,但不是真正的数组。JavaScript中的arguments就是一个典型的伪数组。arguments对象是在函数内部自动创建的特殊对象,用于存储函数被调用时传入的所有实参(即形参对应的实际值)。arguments对象中包含一个类数组的结构,存储了这些实参,并且可以通过下标访问它们。下面是关于arguments伪数组的一些说明:

  1. Object.prototype.toString.call(arguments)可以用来检测一个对象是否为伪数组。对于arguments对象,它返回的结果是'[object Arguments]'

  2. arguments对象具有length属性,这意味着我们可以像数组一样使用下标访问arguments中的元素。例如,arguments[0]表示获取arguments中的第一个参数。

  3. 由于arguments不是真正的数组,所以它没有数组的常用方法,如join()slice()等。如果我们希望将arguments转换为真正的数组,可以使用以下几种方法进行转换:

    • Array.from(arguments):通过Array.from()方法将arguments转换为真正的数组。
    • [...arguments]:使用扩展运算符将arguments转换为数组。 这两种方法都会创建一个新的数组,其中包含与arguments相同的元素。
  4. 如果我们只需要临时使用数组的某个方法,而不希望创建新的数组,可以使用Array.prototype.join.call(arguments, '--')这样的方式。这将调用Array原型上的join()方法,并将arguments作为函数的上下文对象,从而实现了在arguments上调用join()方法。

需要注意的是,伪数组是永久存在的,而通过转换得到的真正数组是临时的,只在转换后的代码段中有效。因此,在使用伪数组时,我们需要根据具体情况选择适当的处理方式。

记忆函数的示例:

记忆函数优化两数相加:

javascript 复制代码
function sum(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 = {}  // 空间换时间   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 memoizedSum = memorize(sum)
console.log(memoizedSum(1, 2));    // 第一次计算,输出 3
console.log(memoizedSum(1, 2));    // 直接从缓存中获取,输出 3
console.log(memoizedSum(4, 6));     // 新的输入,计算并存入缓存,输出 10
console.log(memoizedSum(4, 6));     // 直接从缓存中获取,输出 10

在上面的代码中,我们使用memoizedSum函数来计算两数相加的结果。通过将计算结果存储在缓存中,当函数再次调用时,可以直接从缓存中取出结果,避免了重复计算。

记忆函数优化递归(斐波那契数列):

javascript 复制代码
var fibonacci = function(n){    // 暴击破解法
    return n < 2? n : fibonacci(n - 1) + fibonacci(n - 2)
}
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)
        }
    }
}

总结:

记忆函数是一种优化计算过程的技术,通过将函数的计算结果缓存起来,避免重复计算,提高代码的执行效率。然而,在实际使用中,我们也需要注意记忆函数的适用性和限制。对于输入空间较大的问题,缓存可能会导致内存占用过大,甚至造成内存溢出。因此,在使用记忆函数时,需要权衡利弊,并根据具体情况进行选择和优化。

相关推荐
技术钱几秒前
vue3基于 Vxe Table 实现可拖拽分组 + 动态求和的高级表格
javascript·vue.js
还是大剑师兰特1 分钟前
Vue3 + Element Plus 日期选择器:开始 / 结束时间,结束时间不超过今天
前端·javascript·vue.js
不会写DN2 分钟前
Js常用数组处理
开发语言·javascript·ecmascript
还是大剑师兰特3 分钟前
数组中有两个数据,将其变成字符串
开发语言·javascript·vue.js
Saga Two4 分钟前
Vue实现核心原理
前端·javascript·vue.js
技术钱4 分钟前
vue3实现时间根据系统时区转换对应的时间
javascript·vue.js
殷忆枫11 分钟前
基于STM32的ML307R连接Onenet平台
服务器·前端·javascript
Java 码农12 分钟前
vue cli 环境搭建
前端·javascript·vue.js
酉鬼女又兒17 分钟前
零基础入门前端JavaScript Object 对象完全指南:从基础到进阶(可用于备赛蓝桥杯Web应用开发赛道)
开发语言·前端·javascript·职场和发展·蓝桥杯
RPGMZ20 分钟前
RPGMakerMZ游戏引擎 地图角色顶部显示称号
javascript·游戏引擎·rpgmz·rpgmakermz