数字相加百搭函数——记忆函数

友情提醒:这篇文章所用到的方法在:juejin.cn/post/730453... 这里都有提到

伪数组

在 JavaScript 中,伪数组(Array-like Object)是指具有类数组特性的对象。它们与普通的 JavaScript 数组非常相似,但却不是真正的数组。伪数组具有以下特点:

  1. 拥有 length 属性:伪数组拥有 length 属性,可以通过该属性获取当前元素的个数。
  2. 可以使用下标访问元素:与数组一样,伪数组也可以通过索引来访问元素。
  3. 不具备数组的原型方法:伪数组并不具备数组的原型方法,如 push、pop、slice 等。

常见的伪数组包括 arguments 对象、DOM 元素集合、NodeList 等。例如:

javascriptCopy 复制代码
// arguments 对象是一个伪数组
function test() {
  console.log(arguments.length);
  console.log(arguments[0]);
}
test(1, 2, 3); // 输出:3 1

// DOM 元素集合也是一个伪数组
const divs = document.getElementsByTagName('div');
console.log(divs.length); // 输出 div 元素的个数
console.log(divs[0]); // 输出第一个 div 元素

虽然伪数组不能像数组一样直接调用数组的方法,但它们可以通过 call 或 apply 方法将数组的方法绑定到自身上,从而实现数组的操作。例如:

javascriptCopy 复制代码
// 将数组的 slice 方法绑定到 arguments 对象上
function test() {
  const args = Array.prototype.slice.call(arguments);
  console.log(args.length);
  console.log(args[0]);
}
test(1, 2, 3); // 输出:3 1

总之,伪数组在 JavaScript 中非常常见,需要注意它们的特点和使用方式。

两数相加

以两数相加为例,我们肯定不能写那种很简单的两数相加函数,所以我们限定传递的参数只能是两个:

js 复制代码
function add(a,b){
    if(arguments.length !=2){
       throw new Error('必须传递两个参数')  //超过两个参数就报错 throw Error
    }
    c=a+b
    return c
}
try{
    console.log(add(1,2));
}catch(e){
    console.log(e);
}
console.log('continue....');

优化

摒弃下面那段,我们还可以优化代码。让两数相加传递的参数只允许是整数:

js 复制代码
// 不够优化,得记住之前计算过的
function add(a,b){
    if(arguments.length !== 2 ){
        throw new Error('传递的参数有误');
    }
    if(typeof a!=='number' || typeof b!=='number'){
        throw new Error('必须是整数');
    }
    return a + b
}

记忆函数

我们还可以优化代码。两数相加可以执行很多次,但是如果传递的参数被执行过就会浪费时间,因此我们得让它记住我们之前执行过的参数:

js 复制代码
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 memorizeAdd = memorize(add);
console.log(memorizeAdd(1,2));
console.log(memorizeAdd(1,2));
// memorizeAdd(1,2)  //传到return function(){}

斐波那契数列

让我们拿记忆函数写个斐波那契数列题目:

js 复制代码
let count = 0
var fibonacci = function(n){
    count++
    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)
       }
    }
  }
fibonacci = memorize(fibonacci)
fibonacci(20)
console.log(count);

执行时间已经非常小了。这就是记忆函数的可怕与厉害。

相关推荐
Navigator_Z3 小时前
LeetCode //C - 1089. Duplicate Zeros
c语言·算法·leetcode
wuxia21184 小时前
微信小程序单击元素切换元素的显示和隐藏
javascript·微信小程序·setdata
JustHappy4 小时前
古法编程秘籍(二):什么是代码模块化?别背概念,把房间收拾明白就够了
前端·后端
小江的记录本4 小时前
【JVM虚拟机】堆内存分代模型:年轻代(Eden+Survivor)、老年代、元空间Metaspace(附《思维导图》+《面试高频考点清单》)
java·前端·jvm·后端·python·spring·面试
weixin_471383035 小时前
图片预解码缓存
前端·浏览器缓存·图片预解码
一起学开源5 小时前
一文读懂 ReAct 范式:让 AI Agent 真正学会“思考+行动“
java·javascript·react.js·ecmascript·react·alibaba·智能体开发
云泽8085 小时前
C++ 可调用对象通关指南:深度解析 Lambda 表达式、function 包装器与 bind 绑定器
开发语言·c++·算法
wlsh156 小时前
Go 迭代器
算法
语戚6 小时前
力扣 3161. 块放置查询:线段树解法(Java 实现)
java·算法·leetcode·面试·线段树·力扣·
郑洁文6 小时前
基于网络爬虫的Web敏感信息泄露自动化检测工具
前端·爬虫·网络安全·自动化