Movatterモバイル変換


[0]ホーム

URL:


Shogo Sensui, profile picture
Uploaded byShogo Sensui
2,149 views

Functional JavaScript with Lo-Dash.js

2013/5/25に開催されたFrontrend Vol.5のFunctional JavaScript with Lo-Dash.jsのセッションの資料です。

Embed presentation

Download to read offline
Functional JavaScriptwith Lo-Dash.jsFrontrend Vol.5泉水翔吾 / @1000chCyberAgent, Inc.
About me@1000chWebDeveloper@CyberAgent1年前までProgrammer
Output! http://1000ch.net" @1000ch# http://github.com/1000ch# http://github.com/enja-oss
Agenda! Object-Oriented & Functional! Underscore.js & Lo-Dash.js! Conclusion!
Object-OrientedANDFunctional
Functional ???
Functional Programming! 『数学的な関数の評価を行い、状態やデータの変更を行わないプログラミングパラダイム』
via Wikipedia! 関数型と言われてもイメージしにくい…。
押し寄せるFunctional! HaskellとかClojureとか。! TwitterはScalaを採用。! JavaScriptもFunctional?
哲学的な話をする気はございません!Functionalなアプローチもしてみてねっていう話
Object-Oriented ???
Object-OrientedProgramming! 『オブジェクト同士の相互作用として、システムの振る舞いを捉える考え方』 via Wikipedia! つまり『プログラムで実現したいモデルを抽象化したもの』である。
OOPの例えば…
猫をOOPで表現するvar Animal = function(word) {this.word = word;};Animal.prototype.cry = function() {console.log(this.word);};!var Cat = function() {Animal.call(this, "Nya-");};Cat.prototype = Object.create(Animal.prototype);Cat.prototype.constructor = Animal;!new Cat().cry();//=>Nya-
jQueryもOOP?var $headline = $(".headline");$headline.css({"font-size": "24px"});var $paragraph = $("p");$paragraph.css({"background": "#000","color": "#fff"}).addClass("breakAll");!var $button = $("button");$button.on("click", function() {console.log("button is clicked!");});
オブジェクト指向の問題点
! オブジェクト同士の関係が密になりがち! 役割が大きくなりすぎてクラスが複雑になりがち! 継承されすぎて変更できなくなりがちOOPが抱えがちな問題
œš‘“›⁸コードの役割分担が複雑で、コードの役割が密接な関係を持っているとテストを行うことが難しくなる。’”⁹- @cssradar
at Frontrend Vol.4https://speakerdeck.com/studiomohawk/testable-javascript
つまるところ、保守性を維持しにくい。
jQueryの保守しろって言われても、できません。
Functionalなアプローチが解決してくれる!(かもしれない!)
Funtional Function! 引数が同じであれば出力も同じである! 果たす役割が簡潔で分割されていること
Funtional Function! 引数が同じであれば出力も同じである! 果たす役割が簡潔で分割されていること
This is bad...var sortedString = function(array) {array.sort();
!return array.join();};!var array1 = [1, 6, 8, 4, 9, 0, 3, 5, 2, 7];
!console.log(sortedString(array1));
//=>0,1,2,3,4,5,6,7,8,9
!console.log(array1);
//=>[0,1,2,3,4,5,6,7,8,9]//引数が変更されてしまっている…。

This is better !!!var sortedString = function(array) {var buffer = array.slice();buffer.sort();return buffer.join();};!var array1 = [1, 6, 8, 4, 9, 0, 3, 5, 2, 7];!console.log(sortedString(array1));
//=>0,1,2,3,4,5,6,7,8,9
!console.log(array1);
//=>[1,6,8,4,9,0,3,5,2,7]//OK!

Funtional Function! 引数が同じであれば出力も同じである! 果たす役割が簡潔で分割されていること
This is bad...var setElement = function() {$(".hoge").addClass("decorationClass").animate({...});};var initMainPage = function() {window.scrollTo(1, 0);setElement();};window.onload = function() {initMainPage();};

This is better !!!var setElement = function(element) {$(element).addClass("decorationClass").animate({...});};var hideAddressBar = function() {window.scrollTo(1, 0);};window.onload = function() {hideAddressBar();setElement(document.getElementsByClassName(".hoge"));};

Functionalなアプローチを試してみる。
jQueryっぽいサンプル実装var $ = function(selector) {return {list: document.querySelectorAll(selector),each: function(callback) {for(var i = 0, l = this.list.length;i < l;i++) {callback(this.list[i]);}return this;},addClass: function(className) {return this.each(function(element) {element.classList.add(className);});}};};
使い方イメージ//$コンストラクタにCSSセレクタを渡し、要素にクラスを追加。$(".parentClass .childClass").addClass("hoge");
この実装の問題点! each()もaddClass()もコンストラクタのquerySelectorAllに依存している。! 再利用出来ない。! クラスを拡張するたびにテストの見直し。
Functionalに書き直すvar _ = {};!_.qsa = function(selector) {return document.querySelectorAll(selector);};!_.each = function(targetObject, callback) {for(var i = 0, len = targetObject.length;i < len;i++) {callback(targetObject[i]);}};!_.addClass = function(targetElementList, className) {_.each(targetElementList, function(element) {element.classList.add(className);});};
使い方イメージ//CSSセレクタを渡し、要素を選択する。var elementList = _.qsa(".parentClass .childClass");!!
//取得した要素にクラスを追加する。_.addClass(elementList, "hoge");
解決された点! _.qsa()も、_.addClass()も互いに依存していないので、再利用できる。! テストケースの見直しが発生しにくい。
Functionalなアプローチがもたらすメリット
Simplicityメソッド間の依存性が疎になることで、
コードがシンプルになる。
Testablity関数の役割が簡潔になることで、テストが書きやすくなる。
MaintainablitySimplicityとTestablityによって、
保守性の向上が期待できる。
Underscore.jsANDLo-Dash.js
Functionalなアプローチのメリットはわかった!
ユーティリティをつくったり保守するコストが…。
優秀なライブラリがあります。使いましょう。(※もちろん自作でもOKです)
http://lodash.com/
Lo-Dash.js! Underscore.jsとAPIの互換性のあるライブラリ! each()やfirst()など、便利なユーティリティを備えている
あれ?じゃあUnderscore.jsは?
http://underscorejs.org/
Underscore.jsでもOK! Lo-Dash.jsよりファイルサイズが軽量! コードがとても綺麗なのでコードリーディングに向いてる
なぜLo-Dash.jsを選ぶのか?
- John-David Dalton
at StackOverflowœš‘“›⁸better overall performance andoptimizations for large arrays/objectiteration, and more flexibility withcustom builds and template pre-compilation utilities.’”⁹http://stackoverflow.com/questions/13789618/differences-between-lodash-and-underscore
『大きな配列やオブジェクトの列挙に最適化されており、全体的にパフォーマンスが改善されている。また、カスタムビルドやテンプレートのプリコンパイルなど、より柔軟な作りになっている。』
! 実行パフォーマンスが良い! 問題が色々解決されています! カスタムビルドできます! Underscore.jsに互換性あります
Performance of Lo-Dash.js
Compare Performance(1)Underscore#forEachNative#forEachLo-Dash#forEach with bindLo-Dash#forEachNative#for0 1250000 2500000 3750000 5000000
うーん、やっぱりfor文が1番高速…。
それでもLo-Dash.jsを使う価値がある。
_.each()via Underscore.js
_.each = _.forEach = function(obj, iterator, context) {if (obj == null) return;if (nativeForEach && obj.forEach === nativeForEach) {obj.forEach(iterator, context);} else if (obj.length === +obj.length) {for (var i = 0, l = obj.length; i < l; i++) {if (iterator.call(context, obj[i], i, obj) ===breaker) return;}} else {for (var key in obj) {if (_.has(obj, key)) {if (iterator.call(context, obj[key], key,obj) === breaker) return;}}}};
_.each = _.forEach = function(obj, iterator, context) {if (obj == null) return;if (nativeForEach && obj.forEach === nativeForEach) {obj.forEach(iterator, context);} else if (obj.length === +obj.length) {for (var i = 0, l = obj.length; i < l; i++) {if (iterator.call(context, obj[i], i, obj) ===breaker) return;}} else {for (var key in obj) {if (_.has(obj, key)) {if (iterator.call(context, obj[key], key,obj) === breaker) return;}}}};
_.each = _.forEach = function(obj, iterator, context) {if (obj == null) return;if (nativeForEach && obj.forEach === nativeForEach) {obj.forEach(iterator, context);} else if (obj.length === +obj.length) {for (var i = 0, l = obj.length; i < l; i++) {if (iterator.call(context, obj[i], i, obj) ===breaker) return;}} else {for (var key in obj) {if (_.has(obj, key)) {if (iterator.call(context, obj[key], key,obj) === breaker) return;}}}};ネイティブのforEachが使える場合はそれを実行している
_.each()via Lo-Dash.js
function forEach(collection, callback, thisArg) {var index = -1,length = collection ? collection.length : 0;callback = callback && typeof thisArg == 'undefined' ?callback : lodash.createCallback(callback, thisArg);if (typeof length == 'number') {while (++index < length) {if (callback(collection[index], index,collection) === false) {break;}}} else {forOwn(collection, callback);}return collection;}
function forEach(collection, callback, thisArg) {var index = -1,length = collection ? collection.length : 0;callback = callback && typeof thisArg == 'undefined' ?callback : lodash.createCallback(callback, thisArg);if (typeof length == 'number') {while (++index < length) {if (callback(collection[index], index,collection) === false) {break;}}} else {forOwn(collection, callback);}return collection;}
function forEach(collection, callback, thisArg) {var index = -1,length = collection ? collection.length : 0;callback = callback && typeof thisArg == 'undefined' ?callback : lodash.createCallback(callback, thisArg);if (typeof length == 'number') {while (++index < length) {if (callback(collection[index], index,collection) === false) {break;}}} else {forOwn(collection, callback);}return collection;}基本的にwhile文を使っている
Compare Performance(2)Underscore#forEach ArrayUnderscore#forEach ObjectLo-Dash#forEach ObjectLo-Dash#forEach Array0 550000 1100000 1650000 2200000
Compare Performance(2)Underscore#forEach ArrayUnderscore#forEach ObjectLo-Dash#forEach ObjectLo-Dash#forEach Array0 550000 1100000 1650000 2200000for文とArray.forEachの
差が出てる
Compare Performance(2)Underscore#forEach ArrayUnderscore#forEach ObjectLo-Dash#forEach ObjectLo-Dash#forEach Array0 550000 1100000 1650000 2200000while文なのでほとんど
差が出ていない
カスタムビルドとUnderscore.js互換
Modern build モダンブラウザ向けのビルド。Legacy build レガシーブラウザ対応がなされている。Mobile build 関数のコンパイルがされていないStrict build読み取り専用プロパティを上書きしようとしたときにエラーを投げる。Underscore build Underscore.jsにAPIを合わせてある。Backbone build Backbone.jsに必要なAPIのみ備える。
Modern build モダンブラウザ向けのビルド。Legacy build レガシーブラウザ対応がなされている。Mobile build 関数のコンパイルがされていないStrict build読み取り専用プロパティを上書きしようとしたときにエラーを投げる。Underscore build Underscore.jsにAPIを合わせてある。Backbone build Backbone.jsに必要なAPIのみ備える。
Compare File Sizelodash.min.jslodash.underscore.min.jsunderscore.min.js0 5500 11000 16500 22000compressed gzipped
Compare File Sizelodash.min.jslodash.underscore.min.jsunderscore.min.js0 5500 11000 16500 22000compressed gzippedgzipすればさほど変わらない!(7,701bytes)
色々考慮すると現時点ではLo-Dash.jsが良さそう…。
しかしUnderscore.jsの美しい実装は非常に参考になる。
_.pluck()via Underscore.js
var stooges = [
{name : 'moe', age : 40}, 
{name : 'larry', age : 50}, 
{name : 'curly', age : 60}
];
!_.pluck(stooges, 'name');//=> ["moe", "larry", "curly"]
_.pluck = function(obj, key) {return _.map(obj, function(value){
return value[key];
});};
…美しい。
_.compose = function(/*, funs */) {var functions = arguments;return function() {var args = arguments;for (var i = functions.length - 1; i >= 0; i--) {args = [functions[i].apply(this, args)];}return args[0];};};
var plusFive = function(num) {return num + 5;};var multiplyThree = function(num) {return num * 3;};var plus5_multiply3 = _.compose(multiplyThree, plusFive);plus5_multiply3(4);//=>27
よりFunctionalに書くためにプラグインがあります。
https://github.com/documentcloud/underscore-contrib
_.pipeline = function(/*, funs */){
var functions = arguments;
!return function(seed) {return _.reduce(functions, function(l, r) {return r(l);}, seed);};};
var plusFive = function(num) {return num + 5;};var multiplyThree = function(num) {return num * 3;};var multiply3_plus5 = _.pipeline(multiplyThree, plusFive);multiply3_plus5(4);//=>17
http://dtao.github.io/lazy.js/
function square(x) {
return x * x;
}function inc(x) {
return x + 1;
}function isEven(x) {
return x % 2 === 0;
}!var result = _.chain(array)
.map(square).map(inc)
.filter(isEven).take(5).value();
!var result = Lazy(array)
.map(square).map(inc)
.filter(isEven).take(5);
http://functionaljs.org/
http://moutjs.com/
どれもDOMを操作する実装は含んでいない。※あくまで、JavaScriptのUtilityであるため。
DOM操作のAPIを提供する拡張を作ってみた。※参考程度にどうぞ。
https://github.com/1000ch/_.domextend
特徴! 要素選択API! イベントのバインドAPI! CSSクラスの付け外しAPI! 軽い(minifiedで3KBくらい)
Conclusion !
OBJECT-ORIENTEDTOFUNCTIONAL
OBJECT-ORIENTEDTOFUNCTIONAL
OBJECT-ORIENTEDWITHFUNCTIONAL
物事の抽象化はオブジェクト指向でしかできない。
USE LO-DASH.jSWATCH UNDERSCORE.JS
Underscore.jsとかMOUTあたりが綺麗なので参考に!
Thank you !by@1000ch
http://www.flickr.com/photos/vicpowles/7229138156/http://www.flickr.com/photos/49875617@N06/8770578796/http://www.flickr.com/photos/vicpowles/7229138156/http://www.flickr.com/photos/scalamax/8764370935/http://www.flickr.com/photos/jody_art/8758073909/http://www.flickr.com/photos/liza-photography/6272074016/http://www.flickr.com/photos/51710089@N08/8758089618/Photo Credits
http://fontawesome.io/http://font.ubuntu.com/https://github.com/adobe/Source-Code-Prohttp://www.fontsquirrel.com/fonts/bebas-neueFont Credits

Recommended

PDF
ECMAScript6による関数型プログラミング
PDF
JavaScriptCore.framework の普通な使い方 #cocoa_kansai
PDF
これからのJavaScriptー関数型プログラミングとECMAScript6
PDF
Scalaでプログラムを作りました
PDF
ScalaMatsuri 2016
PPTX
JavaScriptクイックスタート
PDF
Why Reactive Matters #ScalaMatsuri
PDF
Thinking in Cats
PDF
実務者のためのかんたんScalaz
PDF
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
PDF
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
PDF
あなたのScalaを爆速にする7つの方法(日本語版)
PDF
はてなブックマーク in Scala
PDF
サーバーサイドでの非同期処理で色々やったよ
PDF
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
KEY
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
PDF
なぜリアクティブは重要か #ScalaMatsuri
PDF
Phantom Type in Scala
PDF
javascript を Xcode でテスト
PDF
速くなければスマフォじゃない - インターンバージョン-
PDF
JavaScript/CSS 2015 Autumn
PDF
ソーシャルアプリ勉強会(第一回資料)配布用
PDF
「エクストリームエンジニアへの道(Swift編)」
KEY
第3回BDD勉強会
PDF
15分でざっくり分かるScala入門
PDF
Spectron
KEY
BDD勉強会 第6回
PDF
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fall
PDF
JavaScript入門
PDF
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章

More Related Content

PDF
ECMAScript6による関数型プログラミング
PDF
JavaScriptCore.framework の普通な使い方 #cocoa_kansai
PDF
これからのJavaScriptー関数型プログラミングとECMAScript6
PDF
Scalaでプログラムを作りました
PDF
ScalaMatsuri 2016
PPTX
JavaScriptクイックスタート
PDF
Why Reactive Matters #ScalaMatsuri
PDF
Thinking in Cats
ECMAScript6による関数型プログラミング
JavaScriptCore.framework の普通な使い方 #cocoa_kansai
これからのJavaScriptー関数型プログラミングとECMAScript6
Scalaでプログラムを作りました
ScalaMatsuri 2016
JavaScriptクイックスタート
Why Reactive Matters #ScalaMatsuri
Thinking in Cats

What's hot

PDF
実務者のためのかんたんScalaz
PDF
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
PDF
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
PDF
あなたのScalaを爆速にする7つの方法(日本語版)
PDF
はてなブックマーク in Scala
PDF
サーバーサイドでの非同期処理で色々やったよ
PDF
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
KEY
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
PDF
なぜリアクティブは重要か #ScalaMatsuri
PDF
Phantom Type in Scala
PDF
javascript を Xcode でテスト
PDF
速くなければスマフォじゃない - インターンバージョン-
PDF
JavaScript/CSS 2015 Autumn
PDF
ソーシャルアプリ勉強会(第一回資料)配布用
PDF
「エクストリームエンジニアへの道(Swift編)」
KEY
第3回BDD勉強会
PDF
15分でざっくり分かるScala入門
PDF
Spectron
KEY
BDD勉強会 第6回
PDF
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fall
実務者のためのかんたんScalaz
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
あなたのScalaを爆速にする7つの方法(日本語版)
はてなブックマーク in Scala
サーバーサイドでの非同期処理で色々やったよ
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
なぜリアクティブは重要か #ScalaMatsuri
Phantom Type in Scala
javascript を Xcode でテスト
速くなければスマフォじゃない - インターンバージョン-
JavaScript/CSS 2015 Autumn
ソーシャルアプリ勉強会(第一回資料)配布用
「エクストリームエンジニアへの道(Swift編)」
第3回BDD勉強会
15分でざっくり分かるScala入門
Spectron
BDD勉強会 第6回
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fall

Similar to Functional JavaScript with Lo-Dash.js

PDF
JavaScript入門
PDF
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
PDF
わかるコードを書くために For writing clean code
PDF
Chrome Developer Toolsを使いこなそう!
PDF
Effective JavaScript Ch.1
ODP
Javascriptで学ぶ Functional Programming
PDF
traceur-compilerで ECMAScript6を体験
PDF
ちょっと詳しくJavaScript 第2回【関数と引数】
PDF
Ecmascript2015とその周辺について
PDF
JavaScript.Next
PDF
JavaScript 実践講座 Framework, Tool, Performance
PDF
そしてjsの基礎へ戻る#4
PPTX
Nds meetup8 lt
PDF
JavaScript (ECMAScript) 2013
PDF
Kanazawa.js.Next
PDF
Miyazaki.js vol.1 スコープの話
PDF
JavaScript.Next Returns
PDF
ECMAScript 6 Features(PDF 版)
 
PPTX
前期講座09
PDF
エンジニア勉強会_DECIDE
JavaScript入門
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
わかるコードを書くために For writing clean code
Chrome Developer Toolsを使いこなそう!
Effective JavaScript Ch.1
Javascriptで学ぶ Functional Programming
traceur-compilerで ECMAScript6を体験
ちょっと詳しくJavaScript 第2回【関数と引数】
Ecmascript2015とその周辺について
JavaScript.Next
JavaScript 実践講座 Framework, Tool, Performance
そしてjsの基礎へ戻る#4
Nds meetup8 lt
JavaScript (ECMAScript) 2013
Kanazawa.js.Next
Miyazaki.js vol.1 スコープの話
JavaScript.Next Returns
ECMAScript 6 Features(PDF 版)
 
前期講座09
エンジニア勉強会_DECIDE

More from Shogo Sensui

PDF
これからのJavaScriptの話
PDF
Browser Computing Structure
PDF
Introduction to Performance APIs
PDF
Brush up your Coding! 2013 winter
PDF
Introduction to Service Worker
PDF
Brush up your Coding!
PDF
初心者のためのWeb標準技術
PDF
Web Standards 2018
PDF
We should optimize images
PDF
Web Components changes Web Development
PDF
Component of Web Frontend
PDF
Web Standards Interop 2022
PDF
Web フロントエンドの変遷とこれから
PDF
Re-think about Web Performance
PDF
The State of Web Components
PDF
Web Components 2016 & Polymer v2
PDF
Introduction to Resource Hints
これからのJavaScriptの話
Browser Computing Structure
Introduction to Performance APIs
Brush up your Coding! 2013 winter
Introduction to Service Worker
Brush up your Coding!
初心者のためのWeb標準技術
Web Standards 2018
We should optimize images
Web Components changes Web Development
Component of Web Frontend
Web Standards Interop 2022
Web フロントエンドの変遷とこれから
Re-think about Web Performance
The State of Web Components
Web Components 2016 & Polymer v2
Introduction to Resource Hints

Functional JavaScript with Lo-Dash.js


[8]ページ先頭

©2009-2025 Movatter.jp