探索 Sass 3.3 中的 Maps 之 Memoization
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论