• JS性能优化之函数唯一标识以及自记忆函数


    历史小剧场

    朱元璋在平定天下前,曾向谋士征求意见。有一位名叫朱升的学者,告诉朱元璋“高筑墙,广积粮,缓称王”。这条策略在朱元璋最终取得胜利的道路中发挥了重要的作用。

    知识铺垫

    函数可以像对象一样,动态创建和分配属性

    对象拥有的,函数都有

    唯一的区别是:函数是可调用的,即函数会被调用然后去执行某项动作

    • 函数可以通过字面量来创建
    function fn () {}
    
    • 1
    • 函数可以赋值给变量、数组项,或其他对象的属性。
    const fn2 = function () {}
    
    const arr2 = []
    arr2.push(fn2)
    
    const obj2 = {}
    obj2.fn = fn2;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 函数可以作为函数的入参和出参。
    function fn3 (callback) {
      callback()
    }
    fn3(() => console.log('hello'))
    
    • 1
    • 2
    • 3
    • 4
    • 函数可以动态创建和分配属性
    function fn4 () {}
    fn4.name = 'fn4'
    fn4.age = 18
    console.log(fn4) //[Function: fn4] { age: 18 }
    
    • 1
    • 2
    • 3
    • 4

    函数唯一标识

    给函数设置一个 id 属性,作为唯一标识,在某些情况下可以提高性能,比如,
    一个集合中的函数,不希望出现重复函数

    const store = {
        nextId: 1,
        cache: {},
        add(fn) {
            console.log("fn.id => ", fn.id)
            if (!fn.id) {
                fn.id = store.nextId++
                this.cache[fn.id] = fn
            }
        }
    }
    const fun1 = function () {}
    const fun2 = function () {}
    store.add(fun1)
    store.add(fun1)
    store.add(fun2)
    console.log(store.cache)  // { '1': [Function: fun1] { id: 1 }, '2': [Function: fun2] { id: 2 } }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    注意:ES6 的箭头函数是一种匿名函数的简写,它们不具有自己的 this、arguments、super 或 new.target。由于箭头函数的特性,它们不支持添加属性。

    自记忆函数

    过给函数添加属性来记住一些计算结果,之后再调用的时候就可以不用重新计算了,直接去属性中的数据,提高性能。(类似于缓存)以计算素数为例

    function isPrime(value) {
        if (!isPrime.cache) {
            // 给函数添加一个 cache 来存储计算结果
            isPrime.cache = {}
        }
        if (isPrime.cache[value] !== undefined) {
            console.log(`命中缓存${value},直接返回${isPrime.cache[value]}`)
            return isPrime.cache[value]
        }
        let prime = value > 2;
        for (let i = 2; i < value; i++) {
            if (value % i === 0) {
                prime = false;
                break;
            }
        }
        console.log(`缓存里没有${value},结果${prime}存进去`)
        return isPrime.cache[value] = prime;  // 先执行 isPrime.cache[value] = prime, 然后执行 return isPrime.cache[value]
    }
    isPrime(3) // 缓存里没有3,结果true存进去
    isPrime(4) // 缓存里没有4,结果false存进去
    isPrime(5) // 缓存里没有5,结果true存进去
    isPrime(10) // 缓存里没有10,结果false存进去
    isPrime(10) // 命中缓存10,直接返回false
    isPrime(5) // 命中缓存5,直接返回true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    【深度学习】聊一聊什么是卷积神经网络,卷积是什么意思?
    java常见集合
    【C++ 】STL求全排列和组合
    包装接口,处理数据
    2022.12.1 英语背诵
    在MyBatis中,可以使用动态SQL语句来实现对数据的上移、下移和置顶操作
    论文阅读-Federated Social Recommendation with Graph NeuralNetwork
    现代企业架构框架——应用架构
    SB树,看这一篇就够了
    情绪感受一点分享
  • 原文地址:https://blog.csdn.net/qq_42582773/article/details/139104915