Javascript函数缓存的实现及应用场景

 更新时间:2023年12月11日 10:33:56   作者:前端青山  
Javascript函数缓存是一种提高网页性能的重要技术,通过将函数结果存储在缓存中,避免重复计算,从而提高页面加载速度和响应速度,本文主要介绍了Javascript函数缓存的实现及应用场景,具有一定的参考价值,感兴趣的可以了解一下

一、是什么

函数缓存,就是将函数运算过的结果进行缓存

本质上就是用空间(缓存存储)换时间(计算过程)

常用于缓存数据计算结果和缓存对象

const add = (a,b) => a+b;
const calc = memoize(add); // 函数缓存
calc(10,20);// 30
calc(10,20);// 30 缓存

缓存只是一个临时的数据存储,它保存数据,以便将来对该数据的请求能够更快地得到处理

二、如何实现

实现函数缓存主要依靠闭包、柯里化、高阶函数,这里再简单复习下:

闭包

闭包可以理解成,函数 + 函数体内可访问的变量总和

(function() {
    var a = 1;
    function add() {
        const b = 2
        let sum = b + a
        console.log(sum); // 3
    }
    add()
})()

add函数本身,以及其内部可访问的变量,即 a = 1,这两个组合在⼀起就形成了闭包

柯里化

把接受多个参数的函数转换成接受一个单一参数的函数

// 非函数柯里化
var add = function (x,y) {
    return x+y;
}
add(3,4) //7
​
// 函数柯里化
var add2 = function (x) {
    //**返回函数**
    return function (y) {
        return x+y;
    }
}
add2(3)(4) //7

将一个二元函数拆分成两个一元函数

高阶函数

通过接收其他函数作为参数或返回其他函数的函数

function foo(){
  var a = 2;
​
  function bar() {
    console.log(a);
  }
  return bar;
}
var baz = foo();
baz();//2

函数 foo 如何返回另一个函数 barbaz 现在持有对 foo 中定义的bar 函数的引用。由于闭包特性,a的值能够得到

下面再看看如何实现函数缓存,实现原理也很简单,把参数和对应的结果数据存在一个对象中,调用时判断参数对应的数据是否存在,存在就返回对应的结果数据,否则就返回计算结果

如下所示

const memoize = function (func, content) {
  let cache = Object.create(null)
  content = content || this
  return (...key) => {
    if (!cache[key]) {
      cache[key] = func.apply(content, key)
    }
    return cache[key]
  }
}

调用方式也很简单

const calc = memoize(add);
const num1 = calc(100,200)
const num2 = calc(100,200) // 缓存得到的结果

过程分析:

  • 在当前函数作用域定义了一个空对象,用于缓存运行结果

  • 运用柯里化返回一个函数,返回的函数由于闭包特性,可以访问到cache

  • 然后判断输入参数是不是在cache的中。如果已经存在,直接返回cache的内容,如果没有存在,使用函数func对输入参数求值,然后把结果存储在cache

三、应用场景

虽然使用缓存效率是非常高的,但并不是所有场景都适用,因此千万不要极端的将所有函数都添加缓存

以下几种情况下,适合使用缓存:

  • 对于昂贵的函数调用,执行复杂计算的函数

  • 对于具有有限且高度重复输入范围的函数

  • 对于具有重复输入值的递归函数

  • 对于纯函数,即每次使用特定输入调用时返回相同输出的函数

new操作符具体干了什么?

一、是什么

JavaScript中,new操作符用于创建一个给定构造函数的实例对象

例子

function Person(name, age){
    this.name = name;
    this.age = age;
}
Person.prototype.sayName = function () {
    console.log(this.name)
}
const person1 = new Person('Tom', 20)
console.log(person1)  // Person {name: "Tom", age: 20}
t.sayName() // 'Tom'

从上面可以看到:

  • new 通过构造函数 Person 创建出来的实例可以访问到构造函数中的属性

  • new 通过构造函数 Person 创建出来的实例可以访问到构造函数原型链中的属性(即实例与构造函数通过原型链连接了起来)

现在在构建函数中显式加上返回值,并且这个返回值是一个原始类型

function Test(name) {
  this.name = name
  return 1
}
const t = new Test('xxx')
console.log(t.name) // 'xxx'
可以发现,构造函数中返回一个原始值,然而这个返回值并没有作用

下面在构造函数中返回一个对象

function Test(name) {
  this.name = name
  console.log(this) // Test { name: 'xxx' }
  return { age: 26 }
}
const t = new Test('xxx')
console.log(t) // { age: 26 }
console.log(t.name) // 'undefined'

从上面可以发现,构造函数如果返回值为一个对象,那么这个返回值会被正常使用

二、流程

从上面介绍中,我们可以看到new关键字主要做了以下的工作:

  • 创建一个新的对象obj

  • 将对象与构建函数通过原型链连接起来

  • 将构建函数中的this绑定到新建的对象obj

  • 根据构建函数返回类型作判断,如果是原始值则被忽略,如果是返回对象,需要正常处理

举个例子:

function Person(name, age){
    this.name = name;
    this.age = age;
}
const person1 = new Person('Tom', 20)
console.log(person1)  // Person {name: "Tom", age: 20}
t.sayName() // 'Tom'

三、手写new操作符

现在我们已经清楚地掌握了new的执行过程

那么我们就动手来实现一下new

function mynew(Func, ...args) {
    // 1.创建一个新对象
    const obj = {}
    // 2.新对象原型指向构造函数原型对象
    obj.__proto__ = Func.prototype
    // 3.将构建函数的this指向新对象
    let result = Func.apply(obj, args)
    // 4.根据返回值判断
    return result instanceof Object ? result : obj
}

测试一下

function mynew(func, ...args) {
    const obj = {}
    obj.__proto__ = func.prototype
    let result = func.apply(obj, args)
    return result instanceof Object ? result : obj
}
function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.say = function () {
    console.log(this.name)
}
​
let p = mynew(Person, "huihui", 123)
console.log(p) // Person {name: "huihui", age: 123}
p.say() // huihui

可以发现,代码虽然很短,但是能够模拟实现new

到此这篇关于Javascript函数缓存的实现及应用场景的文章就介绍到这了,更多相关Javascript函数缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • JS中的XMLHttpRequest 对象示例详解

    JS中的XMLHttpRequest 对象示例详解

    xmlhttp是一种浏览器对象, 可用于模拟http的GET和POST请求,xmlhttp配合JavaScript可以实现页面数据在无刷新下的定时数据更新,如果应用在聊天室、文字直播上,可以取得较好的视觉效果,这篇文章主要介绍了JS——XMLHttpRequest 对象,需要的朋友可以参考下
    2024-01-01
  • laypage.js分页插件使用方法详解

    laypage.js分页插件使用方法详解

    这篇文章主要为大家详细介绍了laypage.js分页插件的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • JavaScript前端实现快照的示例代码

    JavaScript前端实现快照的示例代码

    snapshot 翻译为快照,用于直观获取页面在某个运行时的状态,本文主要为大家详细介绍 snapshot 工具实现的原理,以及其在项目中的使用,需要的可以参考下
    2023-11-11
  • 微信小程序自定义导航栏实例代码

    微信小程序自定义导航栏实例代码

    这篇文章主要给大家介绍了关于微信小程序自定义导航栏的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用微信小程序具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-04-04
  • JavaScript 手动实现instanceof的方法

    JavaScript 手动实现instanceof的方法

    instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上,本文重点给大家介绍JavaScript手动实现instanceof的问题,感兴趣的朋友跟随小编一起看看吧
    2021-10-10
  • jstree创建无限分级树的方法【基于ajax动态创建子节点】

    jstree创建无限分级树的方法【基于ajax动态创建子节点】

    这篇文章主要介绍了jstree创建无限分级树的方法,结合实例形式分析了jstree基于ajax结合asp.net后台动态创建子节点实现无限分级树效果的相关步骤与操作技巧,需要的朋友可以参考下
    2016-10-10
  • Echarts基本用法_动力节点Java学院整理

    Echarts基本用法_动力节点Java学院整理

    这篇文章主要介绍了Echarts基本用法,详解的介绍了Echarts的基本用法和实例,有兴趣的可以了解一下
    2017-08-08
  • layer弹出的iframe层在执行完毕后关闭当前弹出层的方法

    layer弹出的iframe层在执行完毕后关闭当前弹出层的方法

    今天小编就为大家分享一篇layer弹出的iframe层在执行完毕后关闭当前弹出层的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • Chrome插件(扩展)开发全攻略(完整demo)

    Chrome插件(扩展)开发全攻略(完整demo)

    Chrome插件是一个用Web技术开发、用来增强浏览器功能的软件,它其实就是一个由HTML、CSS、JS、图片等资源组成的一个.crx后缀的压缩包,本文给大家分享一个Chrome插件(扩展)开发全攻略完整demo,感兴趣的朋友跟随小编一起学习下吧
    2021-05-05
  • 详解JS中你不知道的各种循环测速

    详解JS中你不知道的各种循环测速

    在前端JS中,有着多种数组循环的方式:for循环;while和do-while 循环;forEach、map、reduce、filter循环;for-of循环;for-in 循环;那么哪种循环的执行速度最快呢,我们今天来看一看。
    2021-05-05

最新评论