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

More Related Content

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

What's hot

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

Similar to Functional JavaScript with Lo-Dash.js

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

More from Shogo Sensui

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

Functional JavaScript with Lo-Dash.js


[8]ページ先頭

©2009-2025 Movatter.jp