Created
November 27, 2015 12:51
-
-
Save hungtran-it/60dbee0e49901798a70d to your computer and use it in GitHub Desktop.
Lodash
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Finding keys and values | |
| Objects, in Vanilla JavaScript, use the same syntax as arrays | |
| for accessing property | |
| values.That is, the square bracket notation but typically with a human - readable | |
| string, instead of a numerical index.However, the same issues that exist with | |
| numerical indices and arrays exist with objects and keys too.Just because the key | |
| is a string doesn 't mean that we know which keys are available. Sometimes, we | |
| have to search the object to find the key we 're looking for. | |
| We use the findKey() | |
| function to locate the key of the first object property that | |
| callback returns truthy | |
| for: | |
| var object = { | |
| name: 'Gene', | |
| age: 43, | |
| occupation: 'System Administrator' | |
| }; | |
| _.findKey(object, function(value) { | |
| return value === 'Gene'; | |
| }); | |
| // → "name" | |
| Here, the result is name; | |
| since it 's the first property value our callback to findKey() | |
| returns true | |
| for.Strangely enough, the pluck style shorthand doesn 't work the way | |
| you think it might.Calling _.findKey(object, 'Gene') doesn 't find anything. | |
| That 's because it' | |
| s treating each of the property values as nested objects.Here 's an | |
| example of how the where style shorthand works with this | |
| function: | |
| var object = { | |
| programmers: { | |
| Keith: 'C', | |
| Marilyn: 'JavaScript' | |
| }, | |
| designers: { | |
| Lori: 'CSS', | |
| Marilyn: 'HTML' | |
| } | |
| }; | |
| _.findKey(object, { | |
| Marilyn: 'JavaScript' | |
| }); | |
| // → "programmers" | |
| Basic For Each | |
| Just as we saw in the previous chapter, objects can be iterated, just as arrays— they 're | |
| both collections.While the mechanism to do so is slightly different, Lo - Dash abstracts | |
| those differences away behind a unified | |
| function API, as shown in the following code: | |
| var object = { | |
| name: 'Vince', | |
| age: 42, | |
| occupation: 'Architect' | |
| }, | |
| result = []; | |
| _.forOwn(object, function(value, key) { | |
| result.push(key + ': ' + value); | |
| }); | |
| // → | |
| // [ | |
| // "name: Vince", | |
| // "age: 42", | |
| // "occupation: Architect" | |
| // ] | |
| The preceding code should look somewhat familiar.It 's just like the forEach() | |
| function.Instead of the index, the second argument passed to the callback | |
| function | |
| is the property key. | |
| The _.forOwn() and _.forEach() functions behave identically | |
| when applied to an object.Both of these functions share the same | |
| base | |
| function that 's used to iterate over collections. Lo-Dash has | |
| several base functions that are generic enough to serve many | |
| purposes.While these aren 't exposed as a part of the public API, | |
| they make the exposed functions smaller and more comprehensible. | |
| var object = { | |
| name: 'Lois Long', | |
| age: 0, | |
| occupation: null | |
| }; | |
| _.omit(object, function(value) { | |
| return !(!_.isBoolean(value) && value); | |
| }); | |
| // → { name: "Lois Long" } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Rejecting items | |
| Rejecting works much in the same way as filtering does.In the | |
| case of filtering, you | |
| know what you want.In the | |
| case of rejecting, you know what you don 't want. These | |
| rejection operations can be chained together to build complex queries, as shown in | |
| the following code: | |
| var object = { | |
| first: 'Conrad', | |
| last: 'Casey', | |
| age: 37, | |
| enabled: true | |
| }; | |
| _(object) | |
| .reject(_.isBoolean) | |
| .reject(_.isString) | |
| .first() | |
| .toFixed(2); | |
| // → "37.00" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var collection = [ | |
| 1414728000000, | |
| 1383192000000, | |
| 1351656000000, | |
| 1320033600000 | |
| ]; | |
| _(collection) | |
| .map(function(item) { | |
| return new Date(item); | |
| }) | |
| .every(function(item) { | |
| return item.getMonth() === 9 && item.getDate() === 31; | |
| }); | |
| // → true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Using partials | |
| A handy pattern to solve the generic argument issues that arise is to use partials, | |
| that is, partially apply | |
| function arguments using the partial() | |
| function.This lets | |
| us build functions at runtime that can be used repeatedly, without having to always | |
| apply the same arguments.Sometimes it 's not even feasible to provide function | |
| arguments.The following is an example of using partials: | |
| var flattenProp = _.compose(_.flatten, _.prop), | |
| skills = _.partialRight(flattenProp, 'skills'), | |
| names = _.partialRight(flattenProp, 'name'); | |
| var collection = [{ | |
| name: 'Danielle', | |
| skills: ['CSS', 'HTML', 'HTTP'] | |
| }, { | |
| name: 'Candice', | |
| skills: ['Lo-Dash', 'jQuery'] | |
| }, { | |
| name: 'Larry', | |
| skills: ['KineticJS', 'Jasmine'] | |
| }, { | |
| name: 'Norman', | |
| skills: ['Grunt', 'Require'] | |
| }]; | |
| _.contains(skills(collection), 'Lo-Dash'); | |
| // → true | |
| _.contains(names(collection), 'Candice'); | |
| // → true | |
| Our flattenProp() | |
| function is a composition of flatten() and prop(). | |
| The result that is returned is a flattened array.So, | |
| if any of these property | |
| values were themselves arrays, they just get added to the single array. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var collection = _.map(_.range(100), function(item) { | |
| return { | |
| id: item, | |
| age: _.random(50), | |
| enabled: !!_.random() | |
| }; | |
| }); | |
| var indexed = _.groupBy(collection, function(item) { | |
| return +item.enabled * item.age; | |
| }); | |
| console.time('where'); | |
| console.log(_.where(collection, { | |
| age: 25, | |
| enabled: true | |
| })); | |
| console.timeEnd('where'); | |
| // → | |
| // [ | |
| // { id: 23, age: 25, enabled: true }, | |
| // { id: 89, age: 25, enabled: true } | |
| // ] | |
| // where: 5.528ms | |
| console.time('indexed'); | |
| console.log(indexed[25] || []); | |
| console.timeEnd('indexed'); | |
| // → | |
| // [ | |
| // { id: 23, age: 25, enabled: true }, | |
| // { id: 89, age: 25, enabled: true } | |
| // ] | |
| // indexed: 0.712ms |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var collection = _.range(1000000).reverse(); | |
| console.time('motivated'); | |
| _.take(_.filter(collection, function(item) { | |
| return !(item % 10); | |
| }), 10); | |
| console.timeEnd('motivated'); | |
| console.time('lazy'); | |
| _(collection) | |
| .filter(function(item) { | |
| return !(item % 10); | |
| }) | |
| .take(100) | |
| .value(); | |
| console.timeEnd('lazy'); | |
| // → | |
| // motivated: 8.454ms | |
| // lazy: 0.889ms |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Partials | |
| To create a partial | |
| function using Lo - Dash, you use the partial() | |
| function.The | |
| resulting | |
| function then has some arguments presupplied— we don 't have to supply | |
| them again when called.This concept is really useful when we need to dynamically | |
| supply arguments to a | |
| function, just before it 's passed to a new context where those | |
| arguments aren 't available. This is also the case with callbacks, as shown in the | |
| following example: | |
| function sayWhat(what) { | |
| return 'Say, ' + what; | |
| } | |
| var hello = _.partial(sayWhat, 'hello'), | |
| goodbye = _.partial(sayWhat, 'goodbye'); | |
| hello(); | |
| // → "Say, hello" | |
| goodbye(); | |
| // → "Say, goodbye" | |
| The sayWhat() | |
| function builds a simple string based on the supplied string | |
| argument.The two calls to partial() that follow supply this argument.The | |
| hello() and goodbye() functions, when called, will call sayWhat() with their | |
| respective partial arguments. | |
| As we 've seen so far in this chapter, many of the Lo-Dash functions that deal with | |
| functions | |
| return new ones.They also support the arguments passed by the caller. | |
| This is valuable because adding new parameters to our functions doesn 't require | |
| changes to our | |
| function bindings, as shown here: | |
| function greet(greeting, name) { | |
| return greeting + ', ' + name; | |
| } | |
| var hello = _.partial(greet, 'hello'), | |
| goodbye = _.partial(greet, 'goodbye'); | |
| hello('Fran'); | |
| // → "hello, Fran" | |
| goodbye('Jacob'); | |
| // → "goodbye, Jacob" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Function decorators | |
| We can utilize the wrap() | |
| function to decorate a value or another | |
| function with | |
| specific behavior.As with all other Lo - Dash | |
| function helpers, one advantage of | |
| using wrap() is that the caller of the generated | |
| function can supply more data | |
| via arguments, as demonstrated in the following code: | |
| function strong(value) { | |
| return '<strong>' + value + '</strong>'; | |
| } | |
| function regex(exp, val) { | |
| exp = _.isRegExp(exp) ? | |
| exp : new RegExp(exp); | |
| return _.isUndefined(val) ? | |
| exp : exp.exec(val); | |
| } | |
| var boldName = _.wrap('Marianne', strong), | |
| getNumber = _.wrap('(\\d+)', regex); | |
| boldName(); | |
| // → "<strong>Marianne</strong>" | |
| getNumber( | |
| getNumber('abc123')[1]; | |
| // → "123" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Function decorators | |
| We can utilize the wrap() | |
| function to decorate a value or another | |
| function with | |
| specific behavior.As with all other Lo - Dash | |
| function helpers, one advantage of | |
| using wrap() is that the caller of the generated | |
| function can supply more data | |
| via arguments, as demonstrated in the following code: | |
| function strong(value) { | |
| return '<strong>' + value + '</strong>'; | |
| } | |
| function regex(exp, val) { | |
| exp = _.isRegExp(exp) ? | |
| exp : new RegExp(exp); | |
| return _.isUndefined(val) ? | |
| exp : exp.exec(val); | |
| } | |
| var boldName = _.wrap('Marianne', strong), | |
| getNumber = _.wrap('(\\d+)', regex); | |
| boldName(); | |
| // → "<strong>Marianne</strong>" | |
| getNumber( | |
| getNumber('abc123')[1]; | |
| // → "123" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Limiting call counts | |
| There are two Lo - Dash functions that deal with counting the number of times a given | |
| function is called.The after() | |
| function will execute a callback after the composed | |
| function is called a given number of times.The once() | |
| function constrains the given | |
| function to being called only once.Let 's look at after() and see how it works: | |
| function work(value) { | |
| progress(); | |
| } | |
| function reportProgress() { | |
| console.log(++complete + '%'); | |
| progress = complete < 100 ? | |
| _.after(0.01 * collection.length, reportProgress) : | |
| _.noop; | |
| } | |
| var complete = 0, | |
| collection = _.range(9999999), | |
| progress = _.noop; | |
| reportProgress(); | |
| _.forEach(collection, work); | |
| // → | |
| // 1% | |
| // 2% | |
| // 3% | |
| // … |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function toCelsius(degrees) { | |
| return (degrees - 32) * 5 / 9; | |
| } | |
| function toFahrenheit(degrees) { | |
| return degrees * 9 / 5 + 32; | |
| } | |
| var celsius = _.memoize(toCelsius), | |
| fahrenheit = _.memoize(toFahrenheit); | |
| toCelsius(89).toFixed(2) + ' C'; | |
| // → "31.67 C" | |
| celsius(89).toFixed(2) + ' C'; | |
| // → "31.67 C" | |
| toFahrenheit(23).toFixed(2) + ' F'; | |
| // → "73.40 F" | |
| fahrenheit(23).toFixed(2) + ' F'; | |
| // → "73.40 F" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Delaying | |
| function calls | |
| The delay() | |
| function is used to execute a given callback | |
| function after the given | |
| number of milliseconds has elapsed.This actually works the same way as the | |
| built - in setTimeout() | |
| function does.This is shown in the following code: | |
| function poll() { | |
| if (++cnt < max) { | |
| console.log('polling round ' + (cnt + 1)); | |
| timer = _.delay(poll, interval); | |
| } else { | |
| clearTimeout(timer); | |
| } | |
| } | |
| var cnt = -1, | |
| max = 5, | |
| interval = 3000, | |
| timer; | |
| poll(); | |
| // → | |
| // polling round 1 | |
| // polling round 2 | |
| // polling round 3 | |
| // polling round 4 | |
| // polling round 5 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function bytes(b) { | |
| var units = ['B', 'K', 'M', 'G', 'T', 'P'], | |
| target = 0; | |
| while (b >= 1024) { | |
| b = b / 1024; | |
| target++; | |
| } | |
| return (b % 1 === 0 ? b : b.toFixed(1)) + | |
| units[target] + (target === 0 ? '' : 'B'); | |
| } | |
| var collection = [ | |
| 1024, | |
| 1048576, | |
| 345198, | |
| 120120120 | |
| ]; | |
| _.map(collection, bytes); | |
| // → [ "1KB", "1MB", "337.1KB", "114.6MB" ] | |
| The bytes() | |
| function takes a numerical argument, which is the number of bytes | |
| to be formatted.This is the starting unit.We just keep incrementing the target | |
| unit until we have something that is less than 1024. For example, the last item in | |
| our collection maps to '114.6MB'.The bytes() | |
| function can be passed directly | |
| to map() since it 's expecting values in our collection as they are. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var object = { | |
| first: 'Roxanne', | |
| last: 'Elliot', | |
| name: function() { | |
| return this.first + ' ' + this.last; | |
| }, | |
| age: 38, | |
| retirement: 65, | |
| working: function() { | |
| return this.retirement - this.age; | |
| } | |
| }; | |
| _.map(object, function(value, key) { | |
| var item = {}; | |
| item[key] = _.isFunction(value) ? object[key]() : value | |
| return item; | |
| }); | |
| // → | |
| // [ | |
| // { first: "Roxanne" }, | |
| // { last: "Elliot" }, | |
| // { name: "Roxanne Elliot" }, | |
| // { age: 38 }, | |
| // { retirement: 65 }, | |
| // { working: 27 } | |
| // ] | |
| _.map(object, function(value, key) { | |
| var item = {}; | |
| item[key] = _.result(object, key); | |
| return item; | |
| }); | |
| // → | |
| // [ | |
| // { first: "Roxanne" }, | |
| // { last: "Elliot" }, | |
| // { name: "Roxanne Elliot" }, | |
| // { age: 38 }, | |
| // { retirement: 65 }, | |
| // { working: 27 } | |
| // |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment