探索 Sass 3.3 中的 Maps 之 Memoization

发布于 2021-07-14 21:30:20 字数 3355 浏览 1339 评论 0

Memoization 技术已经常期用于其他语言当中,以来提高性能。它涉及到一个函数结果的缓存,是这样的,如果一个函数使用相同的的参数调用两次,那么缓存的副本可以用来替代需要再次计算的值。

话说,我们有现个简单的函数的调用是这样的:

$length1: length(cat, dog, fish);
$length2: length(cat, dog, fish);

在这种情况之下,Sass的length()函数会对列表list(cat,dog,fish)调用两次,可每次计算的长度都是3。

这种计算的开销显然是相当小的,但我们考虑一个不同的功能:

// Fibonacci Function

@function fibonacci($n) {
 $fib: 0 1;
 @for $i from 1 through nth($n,1) {
   $new: nth($fib, length($fib)) + nth($fib, length($fib) - 1);
   $fib: append($fib, $new);
 }
 @return $fib;
}

这就是著名的斐波那契(Fibonacci)函数,他创建了一串数字,每个数字是两个预览数的总和。这个函数可以接受多秒钟编译每次使用的功能,想像一下这样的情况:

$fib1: fibonacci(1000);
$fib2: fibonacci(1000);

你让 Sass 执行完全是相同的,耗费的时间,计算两次。我怀疑你会需要一个斐波那契数列,很多时候,你的网格系统使用了一个函数来制作,它可能会在单个的项目中调用上百次。

Maps 允许我们使用 Memoization 技术,这样当我们调用 fibonacci(1000) 第二次时,我们也不需再计算该值。相反,我们将这些值存储在Maps中,我们需要的时候就可以调用。

如何在项目中创建 Memoization

你可以通过此链接打开一个示例,接下来的内容,我们根据这个示例内容进行阐述。

我们先创建一个全局的变量$memo,并且赋予其一个空的map:

$memo:();

第一件事情是就是创建一个辅助函数memo-update():

@function memo-update($function, $params, $value) {
 $result:();
 @if map-has-key($memo, $function) {
   $sub-map-new: map-merge(map-get($memo,$function),($params: $value));
   $result: map-merge($memo, ($function: ($sub-map-new) ));
 }
 @else {
   $result: map-merge($memo, ($function: ($params: $value)));
 }

 @return $result;
}

这个函数的功能就是检查函数中是否有条目 @if map-has-key($memo,$function)。如果有则更新 sub-map,并且创建新的条目;如果没有则创建一个新的 sub-map。然后返回新的 $memo,并且更新了 $memo Maps。

我们来创建第二个辅助函数 memo-get():

@function memo-get($function, $params) {
  $result: map-get(map-get($memo,$function),$params);
  @return $result;
}

这个函数实现通过 $function 的Key在 $memo 的Map中得到自己的需,然后通过参数 $params 的Key在 map-get($memo,$function) 新产生的Map中得到自己的值。看起来蛮复杂的一样。

最后是我们系统的心脏:call-function()。这个函数调用了前面定义的两个函数。

@function call-function($function, $params...) {
  @if map-has-key($memo, $function) {
      $result: memo-get($function, $params);
      @if $result != null {
          @return $result;
      }
  }
  $result: call($function, $params...);
  $memo: memo-update($function, $params, $result) !global;
  @return $result;
}

当给函数传递参数之后,call-function() 会检查以前是否有调用过。如果有,将会通过 memo-get() 函数检索值。如果之前没用,则使用call()函数,返回结果,并通过 memo-update() 来重组 $memo map。

有了这些功能,我们可能通过 call-function() 或其他函数名以及参数列表。他会从 $memo 的map中索引出值,就算没有,也可以计算出值,并更新到 $memo 的 map 中。

还有很多我们可以做的,而且应该做的,用这些东西可以使其更加强大。

在下周我将会结束Map的这个系列教程。通过这个系列教程,我们可以改善Sass的Maps和如何调用我们的变量,使用变量。在此期间,我阅读了 Mike Crittenden 的 系列教程

英文出处:http://www.phase2technology.com/blog/sass-maps-memoization/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

虐人心

有一天你能到我的心里去,你会看到那里全是你给的伤悲。

0 文章
0 评论
24514 人气
更多

推荐作者

留蓝

文章 0 评论 0

18790681156

文章 0 评论 0

zach7772

文章 0 评论 0

Wini

文章 0 评论 0

ayeshaaroy

文章 0 评论 0

初雪

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文