欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

惰性求值——lodash源码解读

程序员文章站 2022-03-18 15:38:40
前言 lodash受欢迎的一个原因,是其优异的计算性能。而其性能能有这么突出的表现,很大部分就来源于其使用的算法——惰性求值。 本文将讲述lodash源码中,惰性求值的原理和实现。 一、惰性求值的原理分析 惰性求值(Lazy Evaluation),又译为惰性计算、懒惰求值,也称为传需求调用(cal ......

前言

lodash受欢迎的一个原因,是其优异的计算性能。而其性能能有这么突出的表现,很大部分就来源于其使用的算法——惰性求值。
本文将讲述lodash源码中,惰性求值的原理和实现。

一、惰性求值的原理分析

惰性求值(lazy evaluation),又译为惰性计算、懒惰求值,也称为传需求调用(call-by-need),是计算机编程中的一个概念,它的目的是要最小化计算机要做的工作
惰性求值中的参数直到需要时才会进行计算。这种程序实际上是从末尾开始反向执行的。它会判断自己需要返回什么,并继续向后执行来确定要这样做需要哪些值。

以下是how to speed up lo-dash ×100? introducing lazy evaluation.(如何提升lo-dash百倍算力?惰性计算的简介)文中的示例,形象地展示惰性求值。

function pricelt(x) {
   return function(item) { return item.price < x; };
}
var gems = [
   { name: 'sunstone', price: 4 },
   { name: 'amethyst', price: 15 },
   { name: 'prehnite', price: 20},
   { name: 'sugilite', price: 7  },
   { name: 'diopside', price: 3 },
   { name: 'feldspar', price: 13 },
   { name: 'dioptase', price: 2 },
   { name: 'sapphire', price: 20 }
];
 
var chosen = _(gems).filter(pricelt(10)).take(3).value();

程序的目的,是对数据集gems进行筛选,选出3个price小于10的数据。

1.1 一般的做法

如果抛开lodash这个工具库,让你用普通的方式实现var chosen = _(gems).filter(pricelt(10)).take(3);那么,可以用以下方式:
_(gems)拿到数据集,缓存起来。
再执行filter方法,遍历gems数组(长度为10),取出符合条件的数据:

[
   { name: 'sunstone', price: 4 },
   { name: 'sugilite', price: 7  },
   { name: 'diopside', price: 3 },
   { name: 'dioptase', price: 2 }
]

然后,执行take方法,提取前3个数据。

[
   { name: 'sunstone', price: 4 },
   { name: 'sugilite', price: 7  },
   { name: 'diopside', price: 3 }
]

总共遍历的次数为:10+3
执行的示例图如下:

惰性求值——lodash源码解读

1.2 惰性求值做法

普通的做法存在一个问题:每个方法各做各的事,没有协调起来浪费了很多资源。
如果能先把要做的事,用小本本记下来