Movatterモバイル変換


[0]ホーム

URL:


Uploaded byTanUkkii
PDF, PPTX6,539 views

これからのJavaScriptー関数型プログラミングとECMAScript6

2014/9/5にLIG社で行われたWebフロント勉強会で発表した資料です。

Embed presentation

Download as PDF, PPTX
これからのJavaScript 関数型プログラミングとECMAScript 6 /46 1
自己紹介 • 名前:安田裕介 • Trifortに今年4月入社の新卒1年生 • JavaScript, Scala, C++が好き • Webフロントエンジニアやってます • GitHubアカウント: TanUkkii007 この資料に出てくるサンプルコードはhttps://github.com/TanUkkii007/js_pitch_sample_codeにあります /46 2
Webアプリケーション開発の 現状 /46 より大規模に • クライアントマシンのパフォーマンスの向上 • WebブラウザのAPIの充実 • ランタイムの強化 • SPAやMVCの導入 • JavaScriptのサーバーサイドへの進出 3
スケーラブルで保守性の高いコードを JavaScriptで書く必要がある /46 4
どうやって? • 短く書く • 変更しない(させない) /46 5
今日話す内容 /46 • 関数型プログラミング • 第一級オブジェクトとしての関数 • 不変性 • 副作用をなくす • 不変なデータ • ECMAScript 6 • const • 分割代入(デストラクチャリング) • 末尾呼び出し最適化 • for-ofループ 6
関数型プログラミング スケーラブルで保守性の高いコードを構築する手 法として関数型プログラミングが注目されている 関数型のスタイルを言語レベルでサポートしたも のが関数型プログラミング言語 e.g. Lisp, Scheme, SML, Erlang, Haskell, OCaml, F#, Scala /46 7
JavaScriptは関数型プログラミング言語 ではない しかし 関数型プログラミングの考え方は 大規模化するコードに立ち向かう際に 役に立つ /46 8
JavaScriptとは • Javaのシンタックス • Selfのプロトタイプ • Schemeの第一級関数オブジェクト ポータビリティに優れたダイナミックな言語 /46 9
JavaScriptとは • Javaのシンタックス • Selfのプロトタイプ • Schemeの第一級関数オブジェクト JavaScriptの先祖であるSchemeが  関数型プログラミング言語 =>JavaScriptでもある程度関数型プログラミングが可能 10 /46
関数型プログラミングの 構成要素 • 第一級オブジェクトとしての関数 • イミュータビリティ(不変性) 11 /46
• 第一級オブジェクトとしての関数 • イミュータビリティ(不変性) 12 /46
第一級オブジェクトとしての 関数とは オブジェクトとしてのすべての能力をもつ関数である 13 /46
オブジェクト(値)は 1 //変数に代入できる! 2 var one = 1;! 3 //関数からの返り値として返すことができる! 4 function getOne() {! 5 return 1;! 6 }! 7 //関数の引数として渡すことができる! 8 function identity(num) {! 9 return num;! 10 }! 11 //意味はないが値が書けるところにはどこにでも書ける! 12 1;! 13 "1";! 14 //メンバーとしてメソッドをもつ! 15 "1".toString();! 16 //メンバーとしてプロパティをもつ! 17 "1".length;! 14 /46
関数オブジェクトも同様 1 //変数に関数を代入する! 2 var func = function() {};! 3 //関数からの返り値として関数を返す! 4 function emptyFunc() {! 5 return function() {};! 6 }! 7 ///関数の引数として関数を渡す! 8 function result(f) {! 9 return typeof f === 'function' ? f() : f; ! 10 }! 11 //意味はないが値が書けるところにはどこにでも書ける! 12 (function(){});! 13 func;! 14 //関数がメンバーとしてメソッドをもつ! 15 (function(){}).apply(null, []);! 16 //関数がメンバーとしてプロパティをもつ! 17 (function(){}).length;! 15 /46
関数オブジェクトを用いれば 短いコードで柔軟な処理が可能だ Array.prototype.reduceの例 *配列の要素を集約し1つの値にする reduce(callback(prev, next, index, array){}, initial) 16 /46
1 //合計! 2 [0,1,2,3,4,5].reduce(function(prev, current) {! 3 return prev + current;! 4 });! 5 // > 15! 6 //平均! 7 [0,1,2,3,4,5].reduce(function(prev, current, index, array) {! 8 return prev + current/array.length;! 9 });! 10 // > 2.5! 11 //最大値! 12 [0,1,2,3,4,5].reduce(function(prev, current, index, array) {! 13 return prev < current ? current : prev;! 14 });! 15 // > 5! 16 //配列の平坦化! 17 [! 18 [1,2,3,4,5],! 19 [6,7,8,9,10],! 20 [11,12,13,14,15],! 21 [16,17,18,19,20],! 22 ].reduce(function(prev, current) {! 23 return prev.concat(current);! 24 }, []);! 25 // > [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, /46 17, 18, 19, 20]! 17
• 第一級オブジェクトとしての関数 • イミュータビリティ(不変性) 18 /46
JavaScriptはSchemeから 関数オブジェクトを受け継いだが、 イミュータビリティ(不変性)は受け継がな かった /46 ! JavaScriptは ダイナミックであることを選んだ 19
JavaScriptは言語として イミュータビリティを提供しない。 なのでイミュータビリティを実現 したければ、 プログラマーの手によって なしとげなければならない 20 /46
副作用 副作用とは プログラミングにおける副作用(ふくさよう)とは、ある機能が コンピュータの(論理的な)状態を変化させ、それ以降で得られる結 果に影響を与えることをいう。 wikipedia 関数型プログラミングでは副作用を徹底的に排除する 21 /46
/46 副作用をもつ 関数の例 副作用がある関数 は有意な値を返さ ない特徴がある 1 // 1/2! 2 var half = {! 3 numer: 1,! 4 denom: 2! 5 };! 6 console.log(half.numer + '/' + half.denom);! 7 // > 1/2! 8 //halfに1を足す! 9 function plusOne() {! 10 half.numer += half.denom;! 11 }! 12 //rationalをnumで割る! 13 function devide(rational, num) {! 14 rational.denom *= num;! 15 }! 16 plusOne();! 17 // > undefined! 18 console.log(half.numer + '/' + half.denom);! 19 // > 3/2! 20 devide(half, 2);! 21 // > undefined! 22 console.log(half.numer + '/' + half.denom);! 23 // > 3/4! 22
副作用をもたない関数の例 • 外部のデータや状態に依存しない • 外部のデータや状態を変更しない • 引数をもとにただマップ(写像)するだけ 23 /46
1 //分数r1とr2を足す関数! 2 function plus(r1, r2) {! 3 return {! 4 numer: r1.numer*r2.denom + r2.numer* r1.denom,! 5 denom: r1.denom*r2.denom! 6 };! 7 }! 8 // 1/2! 9 var half = {! 10 numer: 1,! 11 denom: 2! 12 };! 13 // 1/4! 14 var quarter = {! 15 numer: 1,! 16 denom: 4! 17 };! 18 // 1/2 + 1/4! 19 var threeOverFour = plus(half, quarter);! 20 ! 21 console.log(threeOverFour.numer + '/' + threeOverFour.denom);! 22 // > 6/8! 23 console.log(half.numer + '/' + half.denom);! 24 // > 1/2! 25 console.log(quarter.numer + '/' + quarter.denom);! 26 // > 1/4 24 /46
副作用をもたない関数の利点 /46 • 汎用性が高い • 安全である • 結果を予測できる 25
おなじみの 副作用をもつ関数 1 // DOM API! 2 image.setAttribute('href', 'image.png');! 3 element.appendChild(child);! 4 element.removeChild(child);! 5 element.classList.add('someclass');! 6 element.classList.remove('someclass');! 7 ! 8 // IO! 9 console.log('side effect'); DOM APIやコンソールへの出力は副作用 副作用はGUIや入出力にはなくてはならないもの 26 /46
関数型プログラミングの手法はModelとController /46 M V C で新価を発揮する 27
イミュータブル(不変)な データをつくる 不変な分数を作りたい /46 ! ! とりあえずオブジェクト指向の考え 方に基づきカプセル化する 28
1 var Rational = function(numer, denom) {! 2 this.numer = numer || 0; this.denom = denom || 1;! 3 };! 4 Rational.prototype = {! 5 toString: function() {! 6 return this.numer + '/' + this.denom;! 7 },! 8 ensure: function(r) {! 9 return (r instanceof Rational)? r: new Rational(r, 1);! 10 },! 11 plus: function(rational) {! 12 var r = this.ensure(rational);! 13 this.numer = this.numer*r.denom + r.numer*this.denom;! 14 this.denom *= r.denom; return this;! 15 },! 16 minus: function(rational) {! 17 var r = this.ensure(rational);! 18 this.numer = this.numer*r.denom - r.numer*this.denom;! 19 this.denom *= r.denom; return this;! 20 },! 21 multiply: function(rational) {! 22 var r = this.ensure(rational);! 23 this.numer *= r.numer;! 24 this.denom *= r.denom; return this;! 25 },! 26 divide: function(rational) {! 27 var r = this.ensure(rational);! 28 this.numer *= r.denom;! 29 this.denom *= r.numer; return this;! 30 }! 31 }; 29 /46 • 自身の状態を変更することに  よって分数の計算を行う • 自分自身を返す
1 // 1/2! 2 var half = new Rational(1,2);! 3 // 1/2! 4 var threeOverTwo = half.plus(1);! 5 ! 6 half === threeOverTwo;! 7 // > true! 8 console.log(half);! 9 // > 3/2! 10 console.log(threeOverTwo);! 11 // > 3/2! 12 ! 13 // 3/2 * 2/3! 14 threeOverTwo.multiply(new Rational(2,3));! 15 // > 6/6! データの状態はメソッドの呼び出しごとに変化していく 30 /46
イミュータブルにする 31 /46
1 var Rational = function(numer, denom) {! 2 this.numer = numer || 0; this.denom = denom || 1;! 3 };! 4 Rational.prototype = {! 5 toString: function() {! 6 return this.numer + '/' + this.denom;! 7 },! 8 ensure: function(r) {! 9 return (r instanceof Rational)? r: new Rational(r, 1);! 10 },! 11 plus: function(rational) {! 12 var r = this.ensure(rational);! 13 var numer = this.numer*r.denom + r.numer*this.denom;! 14 var denom = this.denom * r.denom;! 15 return new Rational(numer, denom);! 16 },! 17 minus: function(rational) {! 18 var r = this.ensure(rational);! 19 var numer = this.numer*r.denom - r.numer*this.denom;! 20 var denom = this.denom * r.denom;! 21 return new Rational(numer, denom);! 22 },! 23 multiply: function(rational) {! 24 var r = this.ensure(rational);! 25 var numer = this.numer * r.numer;! 26 var denom = this.denom * r.denom;! 27 return new Rational(numer, denom);! 28 },! 29 divide: function(rational) { /* omitted */ }! 30 };! 32 /46 • 自身の状態を変更しない • 新しいオブジェクトを返す
1 // 1/2! 2 var half = new Rational(1,2);! 3 ! 4 // 1/2 + 1! 5 var threeOverTwo = half.plus(1);! 6 // > 3/2! 7 // halfとthreeOverTwoは違うオブジェクト! 8 half === threeOverTwo;! 9 // > false! 10 ! 11 console.log(half);! 12 // > 1/2! 13 console.log(threeOverTwo);! 14 // > 3/2! 15 ! 16 3/2 * 2/3! 17 threeOverTwo.multiply(new Rational(2,3));! 18 // > 6/6! 19 ! 20 console.log(threeOverTwo);! 21 // > 3/2! /46 いずれも メソッド呼び出 しの後に 変化していない 33
ES6で導入される 便利な機能 短く、より安全に書けるようになります • const • 分割代入(デストラクチャリング) • 末尾呼び出し最適化 • for-ofループ /46 すべてFF33で動作 34
const • constキーワードを使うことで、再代入不可能な 定数を宣言できる 35 /46
1 const foo = 'foo';! 2 //再代入しても値は変わらない! 3 foo = 'bar';! 4 console.log(foo);! 5 // > foo! 6 ! 7 const cobj = {foo: 'foo'};! 8 //再代入しても値は変わらない! 9 cobj = {};! 10 console.log(cobj.foo);! 11 // > foo! 12 //プロパティは変更できる! 13 cobj.foo = 'bar';! 14 console.log(cobj.foo);! 15 // > bar! 16 ! 17 Object.freeze(cobj);! 18 //Writable is false! 19 cobj.foo = 'baz';! 20 console.log(cobj.foo);! 21 // > 'foo'! 22 //Extensible is false! 23 cobj.bar = 'bar';! 24 console.log(cobj.bar);! 25 // > undefined 36 /46 • const指定された変数は  再代入できない • const指定のオブジェクトでは参照 先は変わらないが、プロパティは変 更できる • プロパティの変更を防ぐには Object.freeze()を慎重に使う
分割代入(デストラクチャリング) • 配列やオブジェクトをパターンで分解し、値を 取り出す • 代入文を逆にしたような構文 • 元の配列やオブジェクトを変更しない • 代入の回数を減らせる 37 /46
1 //配列パターンによる分割! 2 var [a,b] = [1,2];! 3 console.log(a, b);! 4 // > 1 2! 5 ! 6 //従来の値の交換! 7 var tmp = a;! 8 a = b;! 9 b = tmp;! 10 //分割代入による値の交換! 11 [b, a] = [a,b];! 12 ! 13 //オブジェクトパターンによる分割! 14 var half = {numer: 1, denom: 2};! 15 var {numer, a, denom: b} = half;! 16 console.log(a, b);! 17 // > 1 2! 18 ! 19 //ネストも可能! 20 var {name: name, family: {sister: sister}} =! {name: 'John Doe', family: {sister: 1}}! 21 console.log(name, sister);! 22 // "John Doe" 1 38 /46
末尾呼び出し最適化 • 繰り返し計算では関数の再帰の方がループより も短く書ける • 関数内の代入文という副作用を排除できる 39 /46
例えば階乗の計算を 再帰とループの2通りで書いてみると 1 // 再帰による階乗計算! 2 function factorial1(n) {! 3 if (n === 0)! 4 return 1;! 5 return n * factorial1(n - 1);! 6 }! 7 ! 8 //ループによる階乗計算! 9 function factorial2(n) {! 10 var result = 1;! 11 for (var i = 1; i <= n; ++i) {! 12 result *= i;! 13 }! 14 return result;! 15 }! 16 ! 17 // 5 * 4 * 3 * 2 * 1! 18 factorial1(5);! 19 // > 120! 40/46
再帰の問題 • 関数呼び出しのオーバーヘッド • スタックオーバーフローの危険性 ES6で導入される末尾呼び出し最適化 により末尾再帰に限り これらは解決される 41 /46
for-ofループ • オブジェクトの列挙可能なプロパティの名前を列挙する。値ではない。 • 配列のインデックスを文字列にして列挙する。 • prototype中の列挙可能なプロパティも対象にする • 順番が未定義 • カスタマイズ不能 /46 for-inループの問題 for-ofループは値を列挙し、カスタマイズ可能である 42
1 //for-inループはキーを列挙する! 2 for (var i in [1,2,3,4,5])! 3 console.log(i);! 4 // > "0" "1" "2" "3" "4"! 5 ! 6 //for-inループは[[Enumerable]]なprototypeプロパティを列挙する! 7 var F = function() {};! 8 F.prototype = {enumerable: 'enumerable'};! 9 var obj = new F();! 10 for (var key in obj)! 11 console.log(obj[key], obj.hasOwnProperty(key));! 12 // > enumerable false! 13 ! 14 //独自のデータ構造はfor-inでループできない! 15 var LinkedList = function(value, next) {! 16 this.value = value;! 17 this.next = next || null;! 18 };! 19 var list = ! new LinkedList(1, new LinkedList(2, new LinkedList(3)));! 20 for (var curr = list; curr !== null; curr = curr.next)! 21 console.log(curr.value);! 22 // > 1 2 3! 開始、終了、次のデータを知っている必要がある 43/46
1 //for-ofループは値を列挙する 2 for (var i of [1,2,3,4,5]) 3 console.log(i); 4 // > 1 2 3 4 5 5 //@@iteratorを定義すれば、独自のデータ構造もループ可能 6 var LinkedList = function(value, next) { 7 this.value = value; 8 this.next = (next === undefined)? new LinkedList(null, null) /46 : next; 9 }; 10 LinkedList.prototype = { 11 '@@iterator': function() { 12 return { 13 current: this, 14 next: function() { 15 var prev = this.current; 16 this.current = prev.next; 17 return {value: prev.value, done: prev.value === null}; 18 } 19 }; 20 } 21 }; 22 var list = new LinkedList(1, new LinkedList(2, new LinkedList(3))); 23 //@@iteratorの暗黙の呼び出しがおきる 24 for (var value of list) 25 console.log(value); 26 // > 1 2 3 44
@@iteratorの定義が長いって? ジェネレーターつかえば簡単に書けるよ 1 var LinkedList = function(value, next) {! 2 this.value = value;! 3 this.next = (next === undefined)? ! new LinkedList(null, null) : next;! 4 };! 5 LinkedList.prototype = {! 6 //! 7 '@@iterator': function*() {! 8 for (var curr = list; curr.next !== null; curr = /46 curr.next) {! 9 yield curr.value;! 10 }! 11 }! 12 };! 13 var list = ! new LinkedList(1, new LinkedList(2, new LinkedList(3)));! 14 //! 15 for (var value of list)! 16 console.log(value);! 17 // > 1 2 3 45
まとめ • JavaScriptの関数オブジェクトは強力 • 関数、データは副作用をもたないように設計す べき • JavaScriptで不変性を強制することは難しい =>プログラマ自身が努力するしかない • ES6の登場をお楽しみに 46 /46

Recommended

PDF
JavaScript入門
PDF
JavaScriptCore.framework の普通な使い方 #cocoa_kansai
PDF
Spectacular Future with clojure.spec
PDF
ECMAScript6による関数型プログラミング
PDF
はてなブックマーク in Scala
KEY
Clojure programming-chapter-2
PPTX
LINQ 概要 + 結構便利な LINQ to XML
PDF
Frege, What a Non-strict Language
PPTX
C# 7.2 with .NET Core 2.1
PPTX
C# 8.0 Preview in Visual Studio 2019 (16.0)
PDF
なぜリアクティブは重要か #ScalaMatsuri
PDF
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
PPTX
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_ccc
PDF
Objective-C のキャストと Swift の型変換を比べてみる #akibaswift
PDF
並行プログラミングと継続モナド
PPT
Rpscala2011 0601
PPTX
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
PDF
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
PDF
あなたのScalaを爆速にする7つの方法(日本語版)
PDF
Effective Modern C++ 読書会 Item 35
PDF
はてなブックマークにおけるアクセス制御 - 半環構造に基づくモデル化
PDF
JavaScript 講習会 #1
 
PDF
Java SE 8 lambdaで変わる プログラミングスタイル
PDF
JSクラス定義
PDF
15分でざっくり分かるScala入門
PPTX
Sns suite presentation
PDF
Thinking in Cats
PDF
GoCon 2015 Summer GoのASTをいじくって新しいツールを作る
PPTX
Getting started with ES6 : Future of javascript
PPTX
Startup JavaScript

More Related Content

PDF
JavaScript入門
PDF
JavaScriptCore.framework の普通な使い方 #cocoa_kansai
PDF
Spectacular Future with clojure.spec
PDF
ECMAScript6による関数型プログラミング
PDF
はてなブックマーク in Scala
KEY
Clojure programming-chapter-2
PPTX
LINQ 概要 + 結構便利な LINQ to XML
PDF
Frege, What a Non-strict Language
JavaScript入門
JavaScriptCore.framework の普通な使い方 #cocoa_kansai
Spectacular Future with clojure.spec
ECMAScript6による関数型プログラミング
はてなブックマーク in Scala
Clojure programming-chapter-2
LINQ 概要 + 結構便利な LINQ to XML
Frege, What a Non-strict Language

What's hot

PPTX
C# 7.2 with .NET Core 2.1
PPTX
C# 8.0 Preview in Visual Studio 2019 (16.0)
PDF
なぜリアクティブは重要か #ScalaMatsuri
PDF
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
PPTX
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_ccc
PDF
Objective-C のキャストと Swift の型変換を比べてみる #akibaswift
PDF
並行プログラミングと継続モナド
PPT
Rpscala2011 0601
PPTX
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
PDF
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
PDF
あなたのScalaを爆速にする7つの方法(日本語版)
PDF
Effective Modern C++ 読書会 Item 35
PDF
はてなブックマークにおけるアクセス制御 - 半環構造に基づくモデル化
PDF
JavaScript 講習会 #1
 
PDF
Java SE 8 lambdaで変わる プログラミングスタイル
PDF
JSクラス定義
PDF
15分でざっくり分かるScala入門
PPTX
Sns suite presentation
PDF
Thinking in Cats
PDF
GoCon 2015 Summer GoのASTをいじくって新しいツールを作る
C# 7.2 with .NET Core 2.1
C# 8.0 Preview in Visual Studio 2019 (16.0)
なぜリアクティブは重要か #ScalaMatsuri
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_ccc
Objective-C のキャストと Swift の型変換を比べてみる #akibaswift
並行プログラミングと継続モナド
Rpscala2011 0601
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
Java8 コーディングベストプラクティス and NetBeansのメモリログから...
あなたのScalaを爆速にする7つの方法(日本語版)
Effective Modern C++ 読書会 Item 35
はてなブックマークにおけるアクセス制御 - 半環構造に基づくモデル化
JavaScript 講習会 #1
 
Java SE 8 lambdaで変わる プログラミングスタイル
JSクラス定義
15分でざっくり分かるScala入門
Sns suite presentation
Thinking in Cats
GoCon 2015 Summer GoのASTをいじくって新しいツールを作る

Viewers also liked

PPTX
Getting started with ES6 : Future of javascript
PPTX
Startup JavaScript
PDF
はじめてのWallaby.js
PDF
Prototypeベース in JavaScript
PDF
CRDT in 15 minutes
PDF
ECMAScript 6 Features(PDF 版)
 
PDF
プログラミング言語Scala
PPTX
ES6 - JavaCro 2016
PDF
Isomorphic web development with scala and scala.js
PDF
JavaScript 実践講座 Framework, Tool, Performance
PDF
JavaScript.Next Returns
PDF
ES6 はじめました
PDF
150421 es6とかな話
PDF
jQuery勉強会#4
PDF
kontainer-js
PPTX
Architecture of Falcon, a new chat messaging backend system build on Scala
PDF
アニメーションの実装つらい話
PPT
Google App EngineでTwitterアプリを作ろう
PDF
FileReader and canvas and server silde
PPTX
JavaScript : What is it really? AND Some new features in ES6
Getting started with ES6 : Future of javascript
Startup JavaScript
はじめてのWallaby.js
Prototypeベース in JavaScript
CRDT in 15 minutes
ECMAScript 6 Features(PDF 版)
 
プログラミング言語Scala
ES6 - JavaCro 2016
Isomorphic web development with scala and scala.js
JavaScript 実践講座 Framework, Tool, Performance
JavaScript.Next Returns
ES6 はじめました
150421 es6とかな話
jQuery勉強会#4
kontainer-js
Architecture of Falcon, a new chat messaging backend system build on Scala
アニメーションの実装つらい話
Google App EngineでTwitterアプリを作ろう
FileReader and canvas and server silde
JavaScript : What is it really? AND Some new features in ES6

Similar to これからのJavaScriptー関数型プログラミングとECMAScript6

PDF
関数プログラミング入門
PDF
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
PDF
関数型プログラミング in javascript
PDF
わかるコードを書くために For writing clean code
PDF
ECMAScript没proposal追悼式
PDF
Effective JavaScript Ch.1
PDF
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 1 章
PPTX
JavaScriptクイックスタート
PDF
Miyazaki.js vol.1 スコープの話
PPTX
Nds meetup8 lt
PDF
JavaScript/CSS 2015 Autumn
PDF
Kanazawa.js.Next
PPTX
前期講座09
PDF
JavaScript (ECMAScript) 2013
PDF
traceur-compilerで ECMAScript6を体験
PDF
これからの「言語」の話をしよう ―― 未来を生きるためのツール
ODP
Javascriptで学ぶ Functional Programming
PDF
JavaScript.Next
PDF
Javascripでオブジェクト指向
PDF
150420 flash004 変数
関数プログラミング入門
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
関数型プログラミング in javascript
わかるコードを書くために For writing clean code
ECMAScript没proposal追悼式
Effective JavaScript Ch.1
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 1 章
JavaScriptクイックスタート
Miyazaki.js vol.1 スコープの話
Nds meetup8 lt
JavaScript/CSS 2015 Autumn
Kanazawa.js.Next
前期講座09
JavaScript (ECMAScript) 2013
traceur-compilerで ECMAScript6を体験
これからの「言語」の話をしよう ―― 未来を生きるためのツール
Javascriptで学ぶ Functional Programming
JavaScript.Next
Javascripでオブジェクト指向
150420 flash004 変数

More from TanUkkii

PDF
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けー
PDF
Scalaによる型安全なエラーハンドリング
PDF
Distributed ID generator in ChatWork
PDF
すべてのアクター プログラマーが知るべき 単一責務原則とは何か
PPTX
JSON CRDT
PPTX
Akka Clusterの耐障害設計
PPTX
スケールするシステムにおけるエンティティの扱いと 分散ID生成
PDF
Non-blocking IO to tame distributed systems ー How and why ChatWork uses async...
PPTX
Akka HTTP
PDF
ディープニューラルネット入門
PDF
プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー
PDF
WaveNet
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けー
Scalaによる型安全なエラーハンドリング
Distributed ID generator in ChatWork
すべてのアクター プログラマーが知るべき 単一責務原則とは何か
JSON CRDT
Akka Clusterの耐障害設計
スケールするシステムにおけるエンティティの扱いと 分散ID生成
Non-blocking IO to tame distributed systems ー How and why ChatWork uses async...
Akka HTTP
ディープニューラルネット入門
プログラミング言語のパラダイムシフト(ダイジェスト)ーScalaから見る関数型と並列性時代の幕開けー
WaveNet

これからのJavaScriptー関数型プログラミングとECMAScript6

  • 1.
  • 2.
    自己紹介 • 名前:安田裕介• Trifortに今年4月入社の新卒1年生 • JavaScript, Scala, C++が好き • Webフロントエンジニアやってます • GitHubアカウント: TanUkkii007 この資料に出てくるサンプルコードはhttps://github.com/TanUkkii007/js_pitch_sample_codeにあります /46 2
  • 3.
    Webアプリケーション開発の 現状 /46より大規模に • クライアントマシンのパフォーマンスの向上 • WebブラウザのAPIの充実 • ランタイムの強化 • SPAやMVCの導入 • JavaScriptのサーバーサイドへの進出 3
  • 4.
  • 5.
    どうやって? • 短く書く• 変更しない(させない) /46 5
  • 6.
    今日話す内容 /46 •関数型プログラミング • 第一級オブジェクトとしての関数 • 不変性 • 副作用をなくす • 不変なデータ • ECMAScript 6 • const • 分割代入(デストラクチャリング) • 末尾呼び出し最適化 • for-ofループ 6
  • 7.
    関数型プログラミング スケーラブルで保守性の高いコードを構築する手 法として関数型プログラミングが注目されている関数型のスタイルを言語レベルでサポートしたも のが関数型プログラミング言語 e.g. Lisp, Scheme, SML, Erlang, Haskell, OCaml, F#, Scala /46 7
  • 8.
    JavaScriptは関数型プログラミング言語 ではない しかし関数型プログラミングの考え方は 大規模化するコードに立ち向かう際に 役に立つ /46 8
  • 9.
    JavaScriptとは • Javaのシンタックス• Selfのプロトタイプ • Schemeの第一級関数オブジェクト ポータビリティに優れたダイナミックな言語 /46 9
  • 10.
    JavaScriptとは • Javaのシンタックス• Selfのプロトタイプ • Schemeの第一級関数オブジェクト JavaScriptの先祖であるSchemeが  関数型プログラミング言語 =>JavaScriptでもある程度関数型プログラミングが可能 10 /46
  • 11.
    関数型プログラミングの 構成要素 •第一級オブジェクトとしての関数 • イミュータビリティ(不変性) 11 /46
  • 12.
    • 第一級オブジェクトとしての関数 •イミュータビリティ(不変性) 12 /46
  • 13.
  • 14.
    オブジェクト(値)は 1 //変数に代入できる!2 var one = 1;! 3 //関数からの返り値として返すことができる! 4 function getOne() {! 5 return 1;! 6 }! 7 //関数の引数として渡すことができる! 8 function identity(num) {! 9 return num;! 10 }! 11 //意味はないが値が書けるところにはどこにでも書ける! 12 1;! 13 "1";! 14 //メンバーとしてメソッドをもつ! 15 "1".toString();! 16 //メンバーとしてプロパティをもつ! 17 "1".length;! 14 /46
  • 15.
    関数オブジェクトも同様 1 //変数に関数を代入する!2 var func = function() {};! 3 //関数からの返り値として関数を返す! 4 function emptyFunc() {! 5 return function() {};! 6 }! 7 ///関数の引数として関数を渡す! 8 function result(f) {! 9 return typeof f === 'function' ? f() : f; ! 10 }! 11 //意味はないが値が書けるところにはどこにでも書ける! 12 (function(){});! 13 func;! 14 //関数がメンバーとしてメソッドをもつ! 15 (function(){}).apply(null, []);! 16 //関数がメンバーとしてプロパティをもつ! 17 (function(){}).length;! 15 /46
  • 16.
    関数オブジェクトを用いれば 短いコードで柔軟な処理が可能だ Array.prototype.reduceの例*配列の要素を集約し1つの値にする reduce(callback(prev, next, index, array){}, initial) 16 /46
  • 17.
    1 //合計! 2[0,1,2,3,4,5].reduce(function(prev, current) {! 3 return prev + current;! 4 });! 5 // > 15! 6 //平均! 7 [0,1,2,3,4,5].reduce(function(prev, current, index, array) {! 8 return prev + current/array.length;! 9 });! 10 // > 2.5! 11 //最大値! 12 [0,1,2,3,4,5].reduce(function(prev, current, index, array) {! 13 return prev < current ? current : prev;! 14 });! 15 // > 5! 16 //配列の平坦化! 17 [! 18 [1,2,3,4,5],! 19 [6,7,8,9,10],! 20 [11,12,13,14,15],! 21 [16,17,18,19,20],! 22 ].reduce(function(prev, current) {! 23 return prev.concat(current);! 24 }, []);! 25 // > [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, /46 17, 18, 19, 20]! 17
  • 18.
    • 第一級オブジェクトとしての関数 •イミュータビリティ(不変性) 18 /46
  • 19.
  • 20.
    JavaScriptは言語として イミュータビリティを提供しない。 なのでイミュータビリティを実現したければ、 プログラマーの手によって なしとげなければならない 20 /46
  • 21.
    副作用 副作用とは プログラミングにおける副作用(ふくさよう)とは、ある機能がコンピュータの(論理的な)状態を変化させ、それ以降で得られる結 果に影響を与えることをいう。 wikipedia 関数型プログラミングでは副作用を徹底的に排除する 21 /46
  • 22.
    /46 副作用をもつ 関数の例副作用がある関数 は有意な値を返さ ない特徴がある 1 // 1/2! 2 var half = {! 3 numer: 1,! 4 denom: 2! 5 };! 6 console.log(half.numer + '/' + half.denom);! 7 // > 1/2! 8 //halfに1を足す! 9 function plusOne() {! 10 half.numer += half.denom;! 11 }! 12 //rationalをnumで割る! 13 function devide(rational, num) {! 14 rational.denom *= num;! 15 }! 16 plusOne();! 17 // > undefined! 18 console.log(half.numer + '/' + half.denom);! 19 // > 3/2! 20 devide(half, 2);! 21 // > undefined! 22 console.log(half.numer + '/' + half.denom);! 23 // > 3/4! 22
  • 23.
    副作用をもたない関数の例 • 外部のデータや状態に依存しない• 外部のデータや状態を変更しない • 引数をもとにただマップ(写像)するだけ 23 /46
  • 24.
    1 //分数r1とr2を足す関数! 2function plus(r1, r2) {! 3 return {! 4 numer: r1.numer*r2.denom + r2.numer* r1.denom,! 5 denom: r1.denom*r2.denom! 6 };! 7 }! 8 // 1/2! 9 var half = {! 10 numer: 1,! 11 denom: 2! 12 };! 13 // 1/4! 14 var quarter = {! 15 numer: 1,! 16 denom: 4! 17 };! 18 // 1/2 + 1/4! 19 var threeOverFour = plus(half, quarter);! 20 ! 21 console.log(threeOverFour.numer + '/' + threeOverFour.denom);! 22 // > 6/8! 23 console.log(half.numer + '/' + half.denom);! 24 // > 1/2! 25 console.log(quarter.numer + '/' + quarter.denom);! 26 // > 1/4 24 /46
  • 25.
    副作用をもたない関数の利点 /46 •汎用性が高い • 安全である • 結果を予測できる 25
  • 26.
    おなじみの 副作用をもつ関数 1// DOM API! 2 image.setAttribute('href', 'image.png');! 3 element.appendChild(child);! 4 element.removeChild(child);! 5 element.classList.add('someclass');! 6 element.classList.remove('someclass');! 7 ! 8 // IO! 9 console.log('side effect'); DOM APIやコンソールへの出力は副作用 副作用はGUIや入出力にはなくてはならないもの 26 /46
  • 27.
  • 28.
    イミュータブル(不変)な データをつくる 不変な分数を作りたい/46 ! ! とりあえずオブジェクト指向の考え 方に基づきカプセル化する 28
  • 29.
    1 var Rational= function(numer, denom) {! 2 this.numer = numer || 0; this.denom = denom || 1;! 3 };! 4 Rational.prototype = {! 5 toString: function() {! 6 return this.numer + '/' + this.denom;! 7 },! 8 ensure: function(r) {! 9 return (r instanceof Rational)? r: new Rational(r, 1);! 10 },! 11 plus: function(rational) {! 12 var r = this.ensure(rational);! 13 this.numer = this.numer*r.denom + r.numer*this.denom;! 14 this.denom *= r.denom; return this;! 15 },! 16 minus: function(rational) {! 17 var r = this.ensure(rational);! 18 this.numer = this.numer*r.denom - r.numer*this.denom;! 19 this.denom *= r.denom; return this;! 20 },! 21 multiply: function(rational) {! 22 var r = this.ensure(rational);! 23 this.numer *= r.numer;! 24 this.denom *= r.denom; return this;! 25 },! 26 divide: function(rational) {! 27 var r = this.ensure(rational);! 28 this.numer *= r.denom;! 29 this.denom *= r.numer; return this;! 30 }! 31 }; 29 /46 • 自身の状態を変更することに  よって分数の計算を行う • 自分自身を返す
  • 30.
    1 // 1/2!2 var half = new Rational(1,2);! 3 // 1/2! 4 var threeOverTwo = half.plus(1);! 5 ! 6 half === threeOverTwo;! 7 // > true! 8 console.log(half);! 9 // > 3/2! 10 console.log(threeOverTwo);! 11 // > 3/2! 12 ! 13 // 3/2 * 2/3! 14 threeOverTwo.multiply(new Rational(2,3));! 15 // > 6/6! データの状態はメソッドの呼び出しごとに変化していく 30 /46
  • 31.
  • 32.
    1 var Rational= function(numer, denom) {! 2 this.numer = numer || 0; this.denom = denom || 1;! 3 };! 4 Rational.prototype = {! 5 toString: function() {! 6 return this.numer + '/' + this.denom;! 7 },! 8 ensure: function(r) {! 9 return (r instanceof Rational)? r: new Rational(r, 1);! 10 },! 11 plus: function(rational) {! 12 var r = this.ensure(rational);! 13 var numer = this.numer*r.denom + r.numer*this.denom;! 14 var denom = this.denom * r.denom;! 15 return new Rational(numer, denom);! 16 },! 17 minus: function(rational) {! 18 var r = this.ensure(rational);! 19 var numer = this.numer*r.denom - r.numer*this.denom;! 20 var denom = this.denom * r.denom;! 21 return new Rational(numer, denom);! 22 },! 23 multiply: function(rational) {! 24 var r = this.ensure(rational);! 25 var numer = this.numer * r.numer;! 26 var denom = this.denom * r.denom;! 27 return new Rational(numer, denom);! 28 },! 29 divide: function(rational) { /* omitted */ }! 30 };! 32 /46 • 自身の状態を変更しない • 新しいオブジェクトを返す
  • 33.
    1 // 1/2!2 var half = new Rational(1,2);! 3 ! 4 // 1/2 + 1! 5 var threeOverTwo = half.plus(1);! 6 // > 3/2! 7 // halfとthreeOverTwoは違うオブジェクト! 8 half === threeOverTwo;! 9 // > false! 10 ! 11 console.log(half);! 12 // > 1/2! 13 console.log(threeOverTwo);! 14 // > 3/2! 15 ! 16 3/2 * 2/3! 17 threeOverTwo.multiply(new Rational(2,3));! 18 // > 6/6! 19 ! 20 console.log(threeOverTwo);! 21 // > 3/2! /46 いずれも メソッド呼び出 しの後に 変化していない 33
  • 34.
    ES6で導入される 便利な機能 短く、より安全に書けるようになります• const • 分割代入(デストラクチャリング) • 末尾呼び出し最適化 • for-ofループ /46 すべてFF33で動作 34
  • 35.
  • 36.
    1 const foo= 'foo';! 2 //再代入しても値は変わらない! 3 foo = 'bar';! 4 console.log(foo);! 5 // > foo! 6 ! 7 const cobj = {foo: 'foo'};! 8 //再代入しても値は変わらない! 9 cobj = {};! 10 console.log(cobj.foo);! 11 // > foo! 12 //プロパティは変更できる! 13 cobj.foo = 'bar';! 14 console.log(cobj.foo);! 15 // > bar! 16 ! 17 Object.freeze(cobj);! 18 //Writable is false! 19 cobj.foo = 'baz';! 20 console.log(cobj.foo);! 21 // > 'foo'! 22 //Extensible is false! 23 cobj.bar = 'bar';! 24 console.log(cobj.bar);! 25 // > undefined 36 /46 • const指定された変数は  再代入できない • const指定のオブジェクトでは参照 先は変わらないが、プロパティは変 更できる • プロパティの変更を防ぐには Object.freeze()を慎重に使う
  • 37.
    分割代入(デストラクチャリング) • 配列やオブジェクトをパターンで分解し、値を取り出す • 代入文を逆にしたような構文 • 元の配列やオブジェクトを変更しない • 代入の回数を減らせる 37 /46
  • 38.
    1 //配列パターンによる分割! 2var [a,b] = [1,2];! 3 console.log(a, b);! 4 // > 1 2! 5 ! 6 //従来の値の交換! 7 var tmp = a;! 8 a = b;! 9 b = tmp;! 10 //分割代入による値の交換! 11 [b, a] = [a,b];! 12 ! 13 //オブジェクトパターンによる分割! 14 var half = {numer: 1, denom: 2};! 15 var {numer, a, denom: b} = half;! 16 console.log(a, b);! 17 // > 1 2! 18 ! 19 //ネストも可能! 20 var {name: name, family: {sister: sister}} =! {name: 'John Doe', family: {sister: 1}}! 21 console.log(name, sister);! 22 // "John Doe" 1 38 /46
  • 39.
    末尾呼び出し最適化 • 繰り返し計算では関数の再帰の方がループよりも短く書ける • 関数内の代入文という副作用を排除できる 39 /46
  • 40.
    例えば階乗の計算を 再帰とループの2通りで書いてみると 1// 再帰による階乗計算! 2 function factorial1(n) {! 3 if (n === 0)! 4 return 1;! 5 return n * factorial1(n - 1);! 6 }! 7 ! 8 //ループによる階乗計算! 9 function factorial2(n) {! 10 var result = 1;! 11 for (var i = 1; i <= n; ++i) {! 12 result *= i;! 13 }! 14 return result;! 15 }! 16 ! 17 // 5 * 4 * 3 * 2 * 1! 18 factorial1(5);! 19 // > 120! 40/46
  • 41.
    再帰の問題 • 関数呼び出しのオーバーヘッド• スタックオーバーフローの危険性 ES6で導入される末尾呼び出し最適化 により末尾再帰に限り これらは解決される 41 /46
  • 42.
    for-ofループ • オブジェクトの列挙可能なプロパティの名前を列挙する。値ではない。• 配列のインデックスを文字列にして列挙する。 • prototype中の列挙可能なプロパティも対象にする • 順番が未定義 • カスタマイズ不能 /46 for-inループの問題 for-ofループは値を列挙し、カスタマイズ可能である 42
  • 43.
    1 //for-inループはキーを列挙する! 2for (var i in [1,2,3,4,5])! 3 console.log(i);! 4 // > "0" "1" "2" "3" "4"! 5 ! 6 //for-inループは[[Enumerable]]なprototypeプロパティを列挙する! 7 var F = function() {};! 8 F.prototype = {enumerable: 'enumerable'};! 9 var obj = new F();! 10 for (var key in obj)! 11 console.log(obj[key], obj.hasOwnProperty(key));! 12 // > enumerable false! 13 ! 14 //独自のデータ構造はfor-inでループできない! 15 var LinkedList = function(value, next) {! 16 this.value = value;! 17 this.next = next || null;! 18 };! 19 var list = ! new LinkedList(1, new LinkedList(2, new LinkedList(3)));! 20 for (var curr = list; curr !== null; curr = curr.next)! 21 console.log(curr.value);! 22 // > 1 2 3! 開始、終了、次のデータを知っている必要がある 43/46
  • 44.
    1 //for-ofループは値を列挙する 2for (var i of [1,2,3,4,5]) 3 console.log(i); 4 // > 1 2 3 4 5 5 //@@iteratorを定義すれば、独自のデータ構造もループ可能 6 var LinkedList = function(value, next) { 7 this.value = value; 8 this.next = (next === undefined)? new LinkedList(null, null) /46 : next; 9 }; 10 LinkedList.prototype = { 11 '@@iterator': function() { 12 return { 13 current: this, 14 next: function() { 15 var prev = this.current; 16 this.current = prev.next; 17 return {value: prev.value, done: prev.value === null}; 18 } 19 }; 20 } 21 }; 22 var list = new LinkedList(1, new LinkedList(2, new LinkedList(3))); 23 //@@iteratorの暗黙の呼び出しがおきる 24 for (var value of list) 25 console.log(value); 26 // > 1 2 3 44
  • 45.
    @@iteratorの定義が長いって? ジェネレーターつかえば簡単に書けるよ 1var LinkedList = function(value, next) {! 2 this.value = value;! 3 this.next = (next === undefined)? ! new LinkedList(null, null) : next;! 4 };! 5 LinkedList.prototype = {! 6 //! 7 '@@iterator': function*() {! 8 for (var curr = list; curr.next !== null; curr = /46 curr.next) {! 9 yield curr.value;! 10 }! 11 }! 12 };! 13 var list = ! new LinkedList(1, new LinkedList(2, new LinkedList(3)));! 14 //! 15 for (var value of list)! 16 console.log(value);! 17 // > 1 2 3 45
  • 46.
    まとめ • JavaScriptの関数オブジェクトは強力• 関数、データは副作用をもたないように設計す べき • JavaScriptで不変性を強制することは難しい =>プログラマ自身が努力するしかない • ES6の登場をお楽しみに 46 /46

[8]ページ先頭

©2009-2025 Movatter.jp