文章博客

技术团队文档示例


3. 纯函数

<blockquote> <p>纯函数是这样一种函数,即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。</p> </blockquote> <p>比如 slice 和 splice,这两个函数的作用并无二致——但是注意,它们各自的方式却大不同,但不管怎么说作用还是一样的。我们说 slice 符合纯函数的定义是因为对相同的输入它保证能返回相同的输出。而 splice 却会嚼烂调用它的那个数组,然后再吐出来;这就会产生可观察到的副作用,即这个数组永久地改变了。</p> <pre><code class="language-javascript">var xs = [1,2,3,4,5]; // 纯的 xs.slice(0,3); //=&gt; [1,2,3] xs.slice(0,3); //=&gt; [1,2,3] xs.slice(0,3); //=&gt; [1,2,3] // 不纯的 xs.splice(0,3); //=&gt; [1,2,3] xs.splice(0,3); //=&gt; [4,5] xs.splice(0,3); //=&gt; []</code></pre> <p>在函数式编程中,我们讨厌这种会改变数据的笨函数。我们追求的是那种可靠的,每次都能返回同样结果的函数,而不是像 splice 这样每次调用后都把数据弄得一团糟的函数,这不是我们想要的。 来看看另一个例子。</p> <pre><code class="language-javascript">// 不纯的 var minimum = 21; var checkAge = function(age) { return age &gt;= minimum; }; // 纯的 var checkAge = function(age) { var minimum = 21; return age &gt;= minimum; }; </code></pre> <p>副作用让一个函数变得不纯是有道理的:从定义上来说,纯函数必须要能够根据相同的输入返回相同的输出;如果函数需要跟外部事物打交道,那么就无法保证这一点了。 我们来仔细了解下为何要坚持这种「相同输入得到相同输出」原则。</p> <h4>追求“纯”的理由</h4> <p>首先,纯函数总能够根据输入来做缓存。实现缓存的一种典型方式是 memoize 技术:</p> <pre><code class="language-javascript">//缓存代理模式 //例如 : f(1,2,3) 必要的时候以空间换时间 //f(1,2,3) //主要形成 cache { // 1,23: 24 //} /**************** 计算乘积 *****************/ var mult = function(){ var a = 1; for ( var i = 0, l = arguments.length; i &lt; l; i++ ){ a = a * arguments[i]; } return a; }; /**************** 计算加和 *****************/ var plus = function(){ var a = 0; for ( var i = 0, l = arguments.length; i &lt; l; i++ ){ a = a + arguments[i]; } return a; }; /**************** 创建缓存代理的工厂 *****************/ var createProxyFactory = function( fn ){ var cache = {}; return function(){ var args = Array.prototype.join.call( arguments, ',' ); if ( args in cache ){ console.log(cache) return cache[ args ]; } return cache[ args ] = fn.apply( this, arguments ); } }; var proxyMult = createProxyFactory( mult ), proxyPlus = createProxyFactory( plus ); console.log ( proxyMult( 1, 2, 3, 4 ) ); // 输出:24 console.log ( proxyMult( 1, 2, 3, 4 ) ); // 输出:24 console.log ( proxyPlus( 1, 2, 3, 4 ) ); // 输出:10 console.log ( proxyPlus( 1, 2, 3, 4 ) ); // 输出:10 console.log ( proxyPlus( 1, 2, 3, 4 ) ); // 输出:10 </code></pre>

页面列表

ITEM_HTML