Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional JavaScript with Lo-Dash.js

Functional JavaScript with Lo-Dash.js

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

Shogo Sensui

May 25, 2013
Tweet

More Decks by Shogo Sensui

Other Decks in Programming

Transcript

  1. ೣΛ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-
  2. 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!"); });
  3. 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] //Ҿ਺͕มߋ͞Εͯ͠·͍ͬͯΔ…ɻ
  4. 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!
  5. This is bad... var setElement = function() { $(".hoge").addClass("decorationClass").animate({...}); };

    var initMainPage = function() { window.scrollTo(1, 0); setElement(); }; window.onload = function() { initMainPage(); };
  6. 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")); };
  7. 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); }); } }; };
  8. 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); }); };
  9. - John-David Dalton at StackOver"ow “better overall performance and optimizations

    for large arrays/object iteration, and more !exibility with custom builds and template pre- compilation utilities.” http://stackover"ow.com/questions/13789618/di#erences-between- lodash-and-underscore
  10. _.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; } } } };
  11. _.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; } } } };
  12. _.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͕࢖͑Δ ৔߹͸ͦΕΛ࣮ߦ͍ͯ͠Δ
  13. 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; }
  14. 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; }
  15. 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จΛ࢖͍ͬͯΔ
  16. Modern build Legacy build Mobile build Strict build Underscore build

    Backbone build Ϟμϯϒϥ΢β޲͚ͷϏϧυɻ ϨΨγʔϒϥ΢βରԠ͕ͳ͞Ε͍ͯΔɻ ؔ਺ͷίϯύΠϧ͕͞Ε͍ͯͳ͍ ಡΈऔΓઐ༻ϓϩύςΟΛ্ॻ͖͠Α͏ ͱͨ͠ͱ͖ʹΤϥʔΛ౤͛Δɻ Underscore.jsʹAPIΛ߹Θͤͯ͋Δɻ Backbone.jsʹඞཁͳAPIͷΈඋ͑Δɻ
  17. Modern build Legacy build Mobile build Strict build Underscore build

    Backbone build Ϟμϯϒϥ΢β޲͚ͷϏϧυɻ ϨΨγʔϒϥ΢βରԠ͕ͳ͞Ε͍ͯΔɻ ؔ਺ͷίϯύΠϧ͕͞Ε͍ͯͳ͍ ಡΈऔΓઐ༻ϓϩύςΟΛ্ॻ͖͠Α͏ ͱͨ͠ͱ͖ʹΤϥʔΛ౤͛Δɻ Underscore.jsʹAPIΛ߹Θͤͯ͋Δɻ Backbone.jsʹඞཁͳAPIͷΈඋ͑Δɻ
  18. Compare File Size lodash.min.js lodash.underscore.min.js underscore.min.js 0 7500 15000 22500

    30000 compressed gzipped gzip͢Ε͹͞΄ͲมΘΒͳ͍ʂ ʢ7,701bytesʣ
  19. var stooges = [ {name : 'moe', age : 40},

    {name : 'larry', age : 50}, {name : 'curly', age : 60} ]; _.pluck(stooges, 'name'); //=> ["moe", "larry", "curly"]
  20. _.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]; }; };
  21. var plusFive = function(num) { return num + 5; };

    var multiplyThree = function(num) { return num * 3; }; var plus5_multiply3 = _.compose(multiplyThree, plusFive); plus5_multiply3(4); //=>27
  22. _.pipeline = function(/*, funs */){ var functions = arguments; return

    function(seed) { return _.reduce(functions, function(l, r) { return r(l); }, seed); }; };
  23. var plusFive = function(num) { return num + 5; };

    var multiplyThree = function(num) { return num * 3; }; var multiply3_plus5 = _.pipeline(multiplyThree, plusFive); multiply3_plus5(4); //=>17
  24. 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);