ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript 関数プログラミングの例分析_JavaScript スキル

JavaScript 関数プログラミングの例分析_JavaScript スキル

WBOY
WBOYオリジナル
2016-05-16 16:02:171284ブラウズ

この記事の例では、JavaScript 関数プログラミングについて説明します。皆さんの参考に共有してください。具体的な分析は次のとおりです。

JS は、他の動的言語と同様に、高階関数を記述することができます。いわゆる高階関数は、関数を操作できる関数です。なぜなら、js では関数は完全なオブジェクトであり、関数型プログラミングの前提条件を提供する第一級の市民に属しているからです。

以下は、js チュートリアルのコード例です。その機能は、配列要素の平均と標準偏差を計算することです。まず、非関数型プログラミングの記述方法をリストします。

var data = [1,1,3,5,5];
var total = 0;
for(var i = 0;i < data.length;i++)
  total += data[i];
var mean = tatal/data.length; //平均数为3
//计算标准差
total = 0;
for(var i = 0;i < data.length;i++){
  var deviation = data[i] - mean;
  tatal += deviation * deviation;
  }
var stddev = Math,.sqrt(total/(data.length-1));//标准差为2
関数型プログラミングを使用するために、いくつかのヘルパー関数を事前定義します。

//将类数组对象转换为真正的数组
function array(a,n){
 return Array.prototype.slice.call(a,n||0);
}
//将函数实参传递至左侧
function partial_left(f){
 var args = arguments;
 return function(){
  var a = array(args,1);
  a = a.concat(array(arguments));
  return f.apply(this,a);
 };
}
//将函数的实参传递至右侧
function partial_right(f){
 var args = arguments;
 return function(){
  var a = array(arguments);
  a = a.concat(array(args,1));
  return f.apply(this,a);
 };
}
//该函数实参被用做模版,
//实参列表中的undefined值会被实际实参值填充。
function partial(f){
 var args = arguments;
 return function(){
  var a = array(args,1);
  var i = 0,j = 0;
  for(;i<a.length;i++)
   if(a[i] === undefined)
    a[i] = arguments[j++];
  a = a.concat(array(arguments,j));
  return f.apply(this,a);
 };
}
//返回一个函数类似于f(g())
function compose(f,g){
 return function(){
  return f.call(this,g.apply(this,arguments));
 };
}
以下に、関数型プログラミングを完全に使用して js コードを示します。

var data = [1,1,3,5,5];
var sum = function(x,y){return x+y;};
var product = function(x,y){return x*y;};
var neg = partial(product,-1);
var square = partial(Math.pow,undefined,2);
var sqrt = partial(Math.pow,undefined,0.5);
var reciprocal = partial(Math.pow,undefined,-1);
//好吧,高潮来鸟 :)
var mean = product(reduce(data,sum),reciprocal(data.length));
var stddev = sqrt(product(reduce(map(data,compose(square,partial(sum,neg(mean)))),sum),reciprocal(sum(data.length,-1))));
reduce 関数と map 関数を除いて、その他の関数は上記に示しています。 Reduce 関数は、Ruby の Inject 関数に似ています。

ary = (1..10).to_a
ary.inject(0) {|sum,i|sum + i} //结果为55
js は次のように記述されます:

var ary = [1,2,3,4,5,6,7,8,9,10]
ary.reduce(function(sum,i){
 return sum + i;
},0);
0 は sum の初期値です。省略した場合、sum は配列の最初の要素の値になります。ここでは省略できます。

map 関数も非常に単純で、配列の各要素を操作し、操作後に配列を返すのと似ています。js コードは次のようになります。 >

a = (1..3).to_a; #数组[1,2,3]
a.map {|x| x*2} #返回新数组[2,4,6]
その長いコード文字列を分析してみましょう:)

sum と product は要素を加算および乗算する関数を定義します。

neg は、product(-1,x) と同等の関数でもあり、負の x 値を意味します。

square 関数は Math.pow(x,2) と同等であり、x の 2 乗値を計算します。ここでは、partial の 2 番目のパラメーターが未定義であることに注意してください。つまり、ここでの仮パラメーターは、最初の実パラメータを入力します。明確にしておきます。square(x) 関数は Math.pow(x,2) と同じです。

sqrt 関数は square に似ており、その関数は Math.pow(x,0.5) と同等であり、x の平方根を計算するのと同等です。

最後の関数 reciprocal は、Math.pow(x,-1) と同等です。つまり、x の負のべき乗を計算することは、x の逆数を計算することと同じです。

上記の関数を組み合わせる方法は次のとおりです :)

まず平均の計算を見てみましょう。これは非常に簡単です。最初に配列要素の合計を計算し、それを配列長の逆数、つまり配列の合計/配列長で乗算します。

最後に、一見難しそうな標準偏差を、内側から外側に見てみるとよいでしょう:

まず、ネガを含むレイヤーを見てください:


以下の作成関数を見てください:
//等价于函数sum(-1 * mean + x)
partial(sum,neg(mean)

マップ関数を見てみましょう:
//下面在源代码上做了等价替换,可以再次等价于:
//square(sum(-1*mean + x)),再次展开(我剥,我剥,我剥洋葱...):
//Math.pow(sum(-1*mean + x),2);
compose(square,sum(-1*mean + x))
//とてもわかりやすいですね! ?つまり、データ内の各要素は平均であり、その結果を 2 乗します。

次に、マップの外側にあるreduce関数を見てみましょう:
map(data,Math.pow(sum(-1*mean + x),2))

次に、逆関数を見てみましょう:
//将前面新数组的每个元素值加起来。
reduce(map(...),sum)

外積関数を見てください:
//等价于求(data.length-1)的倒数
reciprocal(sum(data.length,-1))

最も外側の sqrt は、上記の除算の結果の平方根を求めることを意味します。これを前の非関数型プログラミング コードと比較できます。これは同じです:) これは非常に複雑なコードのようです。怖いけど、分析すると難しくてすぐにゼロになってしまいます。読者の皆さんが、「結局わからない」という場合は、完全にうちの猫の言語表現能力の問題ですので、ぜひ質問してください。
//等价于新数组元素的和除以(data.length-1)
product(reduce(...),reciprocal(...))
説明は終わり、戦いも終わり、これで終わりです。

この記事が皆様の JavaScript プログラミング設計に役立つことを願っています。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。