https://github.com/timoxley/functional-javascript-workshop
Higher Order Functions
- A higher
Higher-order function
is a function that acts on top of other functions, either by taking them as parameters or returning them. simply said a function that takes a function as an argument or returns a function as an output. - Unlike many other languages with mandatory features, JavaScript allows you to use
higher-order functions
more because it has a first-class function . This means that functions can be treated like any other value in JavaScript: like String or Number, Function values can be stored as variables, properties on objects, or passed to other functions as arguments. Function values are actually Objects (inheriting from Function.prototype ) so you can even add properties and store values on them, just like any regular Object. - The main difference between Function and other value types in JavaScript is the call syntax: if the reference to a function is followed by parentheses and some value is separated by an optional comma:
someFunctionValue(arg1, arg2, etc)
, then the function body will be executed with the supplied arguments (if any). - We’ll demonstrate that functions can be passed as values by passing you a function as an argument.
- Example: Implement a function that takes a function as its first argument, a number
num
as its second argument, and then executes the function passed innum
function time.
1234567891011<span class="token keyword">function</span> <span class="token function">repeat</span> <span class="token punctuation">(</span> <span class="token parameter">operation <span class="token punctuation">,</span> num</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> num <span class="token operator"><=</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">;</span><span class="token function">operation</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">return</span> <span class="token function">repeat</span> <span class="token punctuation">(</span> operation <span class="token punctuation">,</span> <span class="token operator">--</span> num <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> repeat <span class="token punctuation">;</span><span class="token comment">// operation: Một hàm, không nhận đối số, không trả về giá trị</span><span class="token comment">// num: số lần gọi operation</span> - Example: Implement a function that takes a function as its first argument, a number
Basic: Map
- The map() method creates a new array with the results of calling a given function on each element of this array.
- Example: Convert code from for loop to
Array#map
- Using
for()
12345678910<span class="token keyword">function</span> <span class="token function">doubleAll</span> <span class="token punctuation">(</span> <span class="token parameter">numbers</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span><span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator"><</span> numbers <span class="token punctuation">.</span> length <span class="token punctuation">;</span> i <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>result <span class="token punctuation">.</span> <span class="token function">push</span> <span class="token punctuation">(</span> numbers <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token operator">*</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">return</span> result <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> doubleAll <span class="token punctuation">;</span>- Using
map()
1234567<span class="token keyword">function</span> <span class="token function">doubleAll</span> <span class="token punctuation">(</span> <span class="token parameter">numbers</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> numbers <span class="token punctuation">.</span> <span class="token function">map</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token function">double</span> <span class="token punctuation">(</span> <span class="token parameter">num</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> num <span class="token operator">*</span> <span class="token number">2</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> doubleAll <span class="token punctuation">;</span> - Using
Basic: Filter
- The filter() method creates a new array filtered down to only the elements from the given array that satisfy the condition performed by the provided function.
filter()
does not execute the function for empty elementsfilter()
does not change the original array- Example: Create a function
getShortMessages
that takes an array of objects with property ‘.message
‘ and returns a message less than 50 characters in length. The function returns an array containing the messages without their container object.1234567891011<span class="token keyword">function</span> <span class="token function">getShortMessages</span> <span class="token punctuation">(</span> <span class="token parameter">messages</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> messages<span class="token punctuation">.</span> <span class="token function">map</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">item</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> item <span class="token punctuation">.</span> message <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">.</span> <span class="token function">filter</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">item</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> item <span class="token punctuation">.</span> length <span class="token operator"><=</span> <span class="token number">50</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> getShortMessages <span class="token punctuation">;</span>
Basic: Every Some
- The every() method checks if all the elements in the array satisfy a certain condition. It returns a
Boolean
value. If all elements are satisfied, returntrue
, otherwise, if only one element is not satisfied, it will returnfalse
.- For example
123456<span class="token keyword">const</span> numbers <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token number">6</span> <span class="token punctuation">,</span> <span class="token number">7</span> <span class="token punctuation">,</span> <span class="token number">8</span> <span class="token punctuation">,</span> <span class="token number">9</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> numbers <span class="token punctuation">.</span> <span class="token function">every</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">number</span> <span class="token punctuation">)</span> <span class="token operator">=></span> number <span class="token operator">></span> <span class="token number">5</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// true</span><span class="token keyword">const</span> numbers <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token number">6</span> <span class="token punctuation">,</span> <span class="token number">7</span> <span class="token punctuation">,</span> <span class="token number">8</span> <span class="token punctuation">,</span> <span class="token number">9</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> numbers <span class="token punctuation">.</span> <span class="token function">every</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">number</span> <span class="token punctuation">)</span> <span class="token operator">=></span> number <span class="token operator">></span> <span class="token number">5</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// false</span> - The some() method iterates all the elements in an array and as long as one element satisfies the condition, the array will return
true
.- For example
123456<span class="token keyword">const</span> numbers <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token number">15</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">,</span> <span class="token number">3</span> <span class="token punctuation">,</span> <span class="token number">4</span> <span class="token punctuation">,</span> <span class="token number">5</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> numbers <span class="token punctuation">.</span> <span class="token function">some</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">number</span> <span class="token punctuation">)</span> <span class="token operator">=></span> number <span class="token operator">></span> <span class="token number">10</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// true</span><span class="token keyword">const</span> numbers <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">,</span> <span class="token number">3</span> <span class="token punctuation">,</span> <span class="token number">4</span> <span class="token punctuation">,</span> <span class="token number">5</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> numbers <span class="token punctuation">.</span> <span class="token function">some</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">number</span> <span class="token punctuation">)</span> <span class="token operator">=></span> number <span class="token operator">></span> <span class="token number">10</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// false</span> - Example: Returns a function that takes a list of valid users and returns a function that returns true if all supplied users exist in the original list of users. You just need to check if the ids match. Use
Array#some
andArray#every
to check every user passed to your return function exists in the array passed to the output function.1234567891011<span class="token keyword">function</span> <span class="token function">checkUsersValid</span> <span class="token punctuation">(</span> <span class="token parameter">goodUsers</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token function">allUsersValid</span> <span class="token punctuation">(</span> <span class="token parameter">submittedUsers</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> submittedUsers <span class="token punctuation">.</span> <span class="token function">every</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">submittedUser</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> goodUsers <span class="token punctuation">.</span> <span class="token function">some</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">goodUser</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> goodUser <span class="token punctuation">.</span> id <span class="token operator">===</span> submittedUser <span class="token punctuation">.</span> id <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> checkUsersValid <span class="token punctuation">;</span>
Basic: Reduce
- The reduce() method executes a user-provided “reduce” callback on each element of the array, in order, passing the return value from the calculation on the previous element. The end result of running the reducer on all the elements of the array is a single value.
- Example: Given an Array of Strings, use Array#reduce to create an object containing the number of times each string appears in the array. Return the tuwonngj argument directly (no console.log needed).123456789<span class="token keyword">function</span> <span class="token function">countWords</span> <span class="token punctuation">(</span> <span class="token parameter">arr</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> arr <span class="token punctuation">.</span> <span class="token function">reduce</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">countMap <span class="token punctuation">,</span> word</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>countMap <span class="token punctuation">[</span> word <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token operator">++</span> countMap <span class="token punctuation">[</span> word <span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token number">1</span> <span class="token punctuation">;</span><span class="token keyword">return</span> countMap <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> countWords <span class="token punctuation">;</span>
Basic: Recursion
Recursion
is a fundamental programming concept that can lead to elegant and efficient solutions to algorithmic problems. In fact,recursion
is so powerful, all repeating behavior can be defined usingarray recursion
. You’ll findrecursion
indispensable when iterating over nested data structures.Function recursion
is a function that calls itself. For example, this recursive function will take an array of words and return an array of those words, capitalized.12345678910<span class="token keyword">function</span> <span class="token function">toUpperArray</span> <span class="token punctuation">(</span> <span class="token parameter">items</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> items <span class="token punctuation">.</span> length <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token comment">// điều kiện kết thúc</span><span class="token keyword">var</span> head <span class="token operator">=</span> items <span class="token punctuation">[</span> <span class="token number">0</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token comment">// item để vận hành</span>head <span class="token operator">=</span> head <span class="token punctuation">.</span> <span class="token function">toUpperCase</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// thực hiện hành động</span><span class="token keyword">var</span> tail <span class="token operator">=</span> items <span class="token punctuation">.</span> <span class="token function">slice</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// tiếp theo</span><span class="token keyword">return</span> <span class="token punctuation">[</span> head <span class="token punctuation">]</span> <span class="token punctuation">.</span> <span class="token function">concat</span> <span class="token punctuation">(</span> <span class="token function">toUpperArray</span> <span class="token punctuation">(</span> tail <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// bước đệ quy</span><span class="token punctuation">}</span><span class="token function">toUpperArray</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token string">"hello"</span> <span class="token punctuation">,</span> <span class="token string">"world"</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => ['HELLO', 'WORLD']</span>- The purpose of this exercise is to familiarize yourself with recursion by implementing a familiar interface using a recursive function.
Basic: Call
- The call() method calls the function with a given
this
value and the arguments provided individually.12345<span class="token keyword">function</span> <span class="token function">Product</span> <span class="token punctuation">(</span> <span class="token parameter">name <span class="token punctuation">,</span> price</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token operator">=</span> name <span class="token punctuation">;</span><span class="token keyword">this</span> <span class="token punctuation">.</span> price <span class="token operator">=</span> price <span class="token punctuation">;</span><span class="token punctuation">}</span> Pototype
is the mechanism for implementing the OOP model of Javascript, where objects inherit the same features. Every object in JavaScript has an internal property called prototype.1234567891011121314<span class="token keyword">var</span> objCreated <span class="token operator">=</span> Object <span class="token punctuation">.</span> <span class="token function">create</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> quack <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">var</span> objCreatedSlash <span class="token operator">=</span> <span class="token punctuation">{</span> quack <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span><span class="token keyword">var</span> object <span class="token operator">=</span> Object <span class="token punctuation">.</span> <span class="token function">create</span> <span class="token punctuation">(</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span>object <span class="token punctuation">.</span> <span class="token function-variable function">quack</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"quack"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">;</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> Object <span class="token punctuation">.</span> <span class="token function">getPrototypeOf</span> <span class="token punctuation">(</span> object <span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token class-name">Object</span> <span class="token punctuation">.</span> prototype <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => false</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> Object <span class="token punctuation">.</span> <span class="token function">getPrototypeOf</span> <span class="token punctuation">(</span> object <span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => true</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token class-name">Object</span> <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function">hasOwnProperty</span> <span class="token punctuation">.</span> <span class="token function">call</span> <span class="token punctuation">(</span> object <span class="token punctuation">,</span> <span class="token string">"quack"</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => true</span><span class="token comment">//check objCreated</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token class-name">Object</span> <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function">hasOwnProperty</span> <span class="token punctuation">.</span> <span class="token function">call</span> <span class="token punctuation">(</span> objCreated <span class="token punctuation">,</span> <span class="token string">"quack"</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => false</span><span class="token comment">//check objCreatedSlash</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token class-name">Object</span> <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function">hasOwnProperty</span> <span class="token punctuation">.</span> <span class="token function">call</span> <span class="token punctuation">(</span> objCreatedSlash <span class="token punctuation">,</span> <span class="token string">"quack"</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => true</span>- What is the difference between the 2 ways of object initialization
Object.create()
is a method that creates a new object, using an existing object as the prototype of the newly created object.{}
Also a method to create a new object, which is shorter and faster to use.
- In Javascript, to write powerful programs, sometimes we need to check if an object matches the type we need, so we can use Object#hasOwnProperty to detect an object has a property. property is defined on its own, that is, not inherited from its prototype.
hasOwnProperty
in Javascript is a method in Object, which checks whether a property exists in Object or not. If the specified property exists in the specified object, it will be returnedtrue
. If it does not exist, the value `fale.- Example: Write a function duckCount that returns the number of arguments passed to it that has the property ‘quack’ defined directly on them. Does not match values inherited from the prototype.12345678<span class="token keyword">function</span> <span class="token function">duckCount</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token class-name">Array</span> <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function">slice</span> <span class="token punctuation">.</span> <span class="token function">call</span> <span class="token punctuation">(</span> arguments <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">filter</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">obj</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token class-name">Object</span> <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function">hasOwnProperty</span> <span class="token punctuation">.</span> <span class="token function">call</span> <span class="token punctuation">(</span> obj <span class="token punctuation">,</span> <span class="token string">"quack"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> length <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> duckCount <span class="token punctuation">;</span>
Partial Application without Bind
Partial application
allows you to create new functions from existing functions, while also modifying some arguments. After setting up the partially applied arguments, you’ll have a new function ready to multiply the rest of the arguments and be able to execute the original function.- More formally: Partial application refers to the process of modifying an argument to a function and creating another function of less rarity
- apply() is the method that calls the specified function with a certain
this
value andarguments
provided as an array (or anarray-like object
). - Example: We have an
add
function that takes 2 arguments and adds them together123456<span class="token keyword">function</span> <span class="token function">add</span> <span class="token punctuation">(</span> <span class="token parameter">x <span class="token punctuation">,</span> y</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> x <span class="token operator">+</span> y <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token function">add</span> <span class="token punctuation">(</span> <span class="token number">10</span> <span class="token punctuation">,</span> <span class="token number">20</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => 30</span> - Now we use
partiallyApply
which takes a function and an argument to ‘Partial application’.- ‘partial application’ the first parameter of the
add
function isx
1234<span class="token keyword">var</span> addTen <span class="token operator">=</span> <span class="token function">partiallyApply</span> <span class="token punctuation">(</span> add <span class="token punctuation">,</span> <span class="token number">10</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// fix `x` to 10</span><span class="token comment">// addTen là một hàm mới nhận y tham số là add, add vẫn được gọi</span>- When we pass the argument to
y
, we can execute the original functionadd
12345<span class="token function">addTen</span> <span class="token punctuation">(</span> <span class="token number">20</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => 30</span><span class="token function">addTen</span> <span class="token punctuation">(</span> <span class="token number">100</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => 110</span><span class="token function">addTen</span> <span class="token punctuation">(</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => 10</span><span class="token comment">// etc</span> - ‘partial application’ the first parameter of the
Partial Application with Bind
- The bind() method is a native Javascript function that helps us to achieve both partial and browser applications. It ensures the function is called from a
this
instance context, with the givenn
arguments. - Example: Use
Function#bind
to implement a logging function that allows you to specify the namespace. You have to take a string namespace and return a function that prints the message to the console with the namespace prepended. Make sure all arguments passed to the returned write function are printed.1234module <span class="token punctuation">.</span> <span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">namespace</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">.</span> <span class="token function">bind</span> <span class="token punctuation">(</span> console <span class="token punctuation">,</span> namespace <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">;</span>
Implement Map with Reduce
- A
map
function applies a function to each item in an array and collects the results in a new Array.123456789<span class="token keyword">var</span> nums <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">,</span> <span class="token number">3</span> <span class="token punctuation">,</span> <span class="token number">4</span> <span class="token punctuation">,</span> <span class="token number">5</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span><span class="token comment">// `map` is your exported function</span><span class="token keyword">var</span> output <span class="token operator">=</span> <span class="token function">map</span> <span class="token punctuation">(</span> nums <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token function">double</span> <span class="token punctuation">(</span> <span class="token parameter">item</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> item <span class="token operator">*</span> <span class="token number">2</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span>console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> output <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// => [2,4,6,8,10]</span> - Example: Use Array#Reduce to implement a simplified version of Array#map1234567module <span class="token punctuation">.</span> <span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">arrayMap</span> <span class="token punctuation">(</span> <span class="token parameter">arr <span class="token punctuation">,</span> fn <span class="token punctuation">,</span> thisArg</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> arr <span class="token punctuation">.</span> <span class="token function">reduce</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">acc <span class="token punctuation">,</span> item <span class="token punctuation">,</span> index <span class="token punctuation">,</span> arr</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>acc <span class="token punctuation">.</span> <span class="token function">push</span> <span class="token punctuation">(</span> <span class="token function">fn</span> <span class="token punctuation">.</span> <span class="token function">call</span> <span class="token punctuation">(</span> thisArg <span class="token punctuation">,</span> item <span class="token punctuation">,</span> index <span class="token punctuation">,</span> arr <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">return</span> acc <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">;</span>
Function Spies
Spies
allow you to monitor a function, they show options for monitoring the number of calls, arguments, and return values. This allows you to write tests to verify the behavior of the function.- Example: Overriding an object’s specified method with new functionality while maintaining all the old behaviour.12345678910111213141516171819<span class="token keyword">function</span> <span class="token function">Spy</span> <span class="token punctuation">(</span> <span class="token parameter">target <span class="token punctuation">,</span> method</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">var</span> originalFunction <span class="token operator">=</span> target <span class="token punctuation">[</span> method <span class="token punctuation">]</span> <span class="token punctuation">;</span><span class="token comment">// sử dụng một đối tượng để chúng ta có thể chuyển bằng tham chiếu, không phải giá trị</span><span class="token comment">// tức là chúng ta có thể trả về kết quả, nhưng số lượng cập nhật từ phạm vi này</span><span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token punctuation">{</span>count <span class="token operator">:</span> <span class="token number">0</span> <span class="token punctuation">,</span><span class="token punctuation">}</span> <span class="token punctuation">;</span><span class="token comment">// thay thế phương thức bằng phương thức gián điệp</span>target <span class="token punctuation">[</span> method <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>result <span class="token punctuation">.</span> count <span class="token operator">++</span> <span class="token punctuation">;</span> <span class="token comment">// hàm theo dõi đã được gọi</span><span class="token keyword">return</span> <span class="token function">originalFunction</span> <span class="token punctuation">.</span> <span class="token function">apply</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">,</span> arguments <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// gọi hàm ban đầu</span><span class="token punctuation">}</span> <span class="token punctuation">;</span><span class="token keyword">return</span> result <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> Spy <span class="token punctuation">;</span><span class="token comment">// taget: một đối tượng chứa phương thức method</span>
Blocking Event Loop
- Example: Modify the recursive
repeat
function provided in the boilerplate, so that it does not block the event loop (i.e. the timer and IO handler can fire). This necessarily requires asynchronous iteration. - The timeout is queued to fire after 100 milliseconds, will print the test’s results and exit the process.
repeat
should release control of the event loop to allow a timeout to interrupt before all operations complete. - Try to do as many operations as you can before the timeout runs out!123456789101112131415161718<span class="token keyword">function</span> <span class="token function">repeat</span> <span class="token punctuation">(</span> <span class="token parameter">operation <span class="token punctuation">,</span> num</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> num <span class="token operator"><=</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">;</span><span class="token function">operation</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token comment">// release control every 10 or so</span><span class="token comment">// iterations.</span><span class="token comment">// 10 is arbitrary.</span><span class="token keyword">if</span> <span class="token punctuation">(</span> num <span class="token operator">%</span> <span class="token number">10</span> <span class="token operator">===</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token function">setTimeout</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token function">repeat</span> <span class="token punctuation">(</span> operation <span class="token punctuation">,</span> <span class="token operator">--</span> num <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span><span class="token function">repeat</span> <span class="token punctuation">(</span> operation <span class="token punctuation">,</span> <span class="token operator">--</span> num <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> repeat <span class="token punctuation">;</span>
Trampoline
- Is a small piece of code that quickly builds on the stack when the address of a nested function is taken.
- Example: Fix the console below that uses a
trampoline
to repeatedly call itself synchronously. You can assume that the operation passed to iterate takes no arguments (or they are already bound to the function) and the return value doesn’t matter.1234567891011121314151617181920<span class="token keyword">function</span> <span class="token function">repeat</span> <span class="token punctuation">(</span> <span class="token parameter">operation <span class="token punctuation">,</span> num</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> num <span class="token operator"><=</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">;</span><span class="token function">operation</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">return</span> <span class="token function">repeat</span> <span class="token punctuation">(</span> operation <span class="token punctuation">,</span> <span class="token operator">--</span> num <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">function</span> <span class="token function">trampoline</span> <span class="token punctuation">(</span> <span class="token parameter">fn</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">while</span> <span class="token punctuation">(</span> fn <span class="token operator">&&</span> <span class="token keyword">typeof</span> fn <span class="token operator">===</span> <span class="token string">"function"</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>fn <span class="token operator">=</span> <span class="token function">fn</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> <span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">operation <span class="token punctuation">,</span> num</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token function">trampoline</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token function">repeat</span> <span class="token punctuation">(</span> operation <span class="token punctuation">,</span> num <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">;</span>
Async Loops
- Example: Edit the code, the callback must be called with all loaded users. The order of users must match the order of the users id provided.1234567891011121314<span class="token keyword">function</span> <span class="token function">loadUsers</span> <span class="token punctuation">(</span> <span class="token parameter">userIds <span class="token punctuation">,</span> load <span class="token punctuation">,</span> done</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">var</span> users <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span><span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator"><</span> userIds <span class="token punctuation">.</span> length <span class="token punctuation">;</span> i <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>users <span class="token punctuation">.</span> <span class="token function">push</span> <span class="token punctuation">(</span> <span class="token function">load</span> <span class="token punctuation">(</span> userIds <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">return</span> users <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> loadUsers <span class="token punctuation">;</span><span class="token comment">// userIds: Mảng gồm id người dùng dạng số</span><span class="token comment">// load: Chức năng sử dụng để tải các đối tượng người dùng</span><span class="token comment">// done: Hàm yêu cầu một Mảng các đối tượng người dùng (như đươc truy xuất từ `load`).</span>
- Fix
12345678910111213<span class="token keyword">function</span> <span class="token function">loadUsers</span> <span class="token punctuation">(</span> <span class="token parameter">userIds <span class="token punctuation">,</span> load <span class="token punctuation">,</span> done</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">var</span> completed <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span><span class="token keyword">var</span> users <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span>userIds <span class="token punctuation">.</span> <span class="token function">forEach</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">id <span class="token punctuation">,</span> index</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token function">load</span> <span class="token punctuation">(</span> id <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">user</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>users <span class="token punctuation">[</span> index <span class="token punctuation">]</span> <span class="token operator">=</span> user <span class="token punctuation">;</span><span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">++</span> completed <span class="token operator">===</span> userIds <span class="token punctuation">.</span> length <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">done</span> <span class="token punctuation">(</span> users <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> loadUsers <span class="token punctuation">;</span>
Recursion
- Example: Implement a recursive function that returns a module’s unique dependencies and child dependencies in alphabetical order. Dependencies are printed as overlay versions.
- Multiple versions of the same module are allowed, but duplicate modules of the same version must be removed.12345678910111213<span class="token keyword">function</span> <span class="token function">getDependencies</span> <span class="token punctuation">(</span> <span class="token parameter">mod <span class="token punctuation">,</span> result</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>result <span class="token operator">=</span> result <span class="token operator">||</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span><span class="token keyword">var</span> dependencies <span class="token operator">=</span> <span class="token punctuation">(</span> mod <span class="token operator">&&</span> mod <span class="token punctuation">.</span> dependencies <span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span>Object <span class="token punctuation">.</span> <span class="token function">keys</span> <span class="token punctuation">(</span> dependencies <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">forEach</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">dep</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">var</span> key <span class="token operator">=</span> dep <span class="token operator">+</span> <span class="token string">"@"</span> <span class="token operator">+</span> mod <span class="token punctuation">.</span> dependencies <span class="token punctuation">[</span> dep <span class="token punctuation">]</span> <span class="token punctuation">.</span> version <span class="token punctuation">;</span><span class="token keyword">if</span> <span class="token punctuation">(</span> result <span class="token punctuation">.</span> <span class="token function">indexOf</span> <span class="token punctuation">(</span> key <span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token operator">-</span> <span class="token number">1</span> <span class="token punctuation">)</span> result <span class="token punctuation">.</span> <span class="token function">push</span> <span class="token punctuation">(</span> key <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token function">getDependencies</span> <span class="token punctuation">(</span> mod <span class="token punctuation">.</span> dependencies <span class="token punctuation">[</span> dep <span class="token punctuation">]</span> <span class="token punctuation">,</span> result <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">return</span> result <span class="token punctuation">.</span> <span class="token function">sort</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> getDependencies <span class="token punctuation">;</span>
Currying
Currying
is an advanced technique for working with functions that simplifies a function by converting a function of many arguments into a sequence of functions of a single argument. It is not only used in Javascript but also used in other languages.- Example: Create a function ‘curryN’ that takes an arbitrary number of arguments, curryN will take two parameters
- fn: The function we want to implement
- n: Number of optional arguments for curry. If not provided, ‘curryN’ should use fn’s arity as the value for ‘n’.
12345678910<span class="token keyword">function</span> <span class="token function">curryN</span> <span class="token punctuation">(</span> <span class="token parameter">fn <span class="token punctuation">,</span> n</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>n <span class="token operator">=</span> n <span class="token operator">||</span> fn <span class="token punctuation">.</span> length <span class="token punctuation">;</span><span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token function">curriedN</span> <span class="token punctuation">(</span> <span class="token parameter">arg</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span> n <span class="token operator"><=</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">fn</span> <span class="token punctuation">(</span> arg <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token keyword">return</span> <span class="token function">curryN</span> <span class="token punctuation">(</span> <span class="token function">fn</span> <span class="token punctuation">.</span> <span class="token function">bind</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">,</span> arg <span class="token punctuation">)</span> <span class="token punctuation">,</span> n <span class="token operator">-</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token punctuation">;</span><span class="token punctuation">}</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> curryN <span class="token punctuation">;</span>
Function Call
- Example: Write a function that allows you to use Array.ptototype.slice without using slice.call or slice.apply to call it.1234567891011121314<span class="token comment">// Giải thích:</span><span class="token comment">// Giá trị của `this` trong Function.call là hàm</span><span class="token comment">// điều đó sẽ được thực thi.</span><span class="token comment">// bind trả về một hàm mới với giá trị là `this` đã được sửa</span><span class="token comment">// cho bất cứ thứ gì đã được truyền làm đối số đầu tiên của nó.</span><span class="token comment">// Mọi hàm 'kế thừa' từ Function.prototype,</span><span class="token comment">// do đó mọi hàm, bao gồm cả lệnh gọi, áp dụng và ràng buộc</span><span class="token comment">// có các phương thức gọi áp dụng và ràng buộc.</span><span class="token comment">// Function.prototype.call === Function.call</span>module <span class="token punctuation">.</span> exports <span class="token operator">=</span> Function <span class="token punctuation">.</span> <span class="token function">call</span> <span class="token punctuation">.</span> <span class="token function">bind</span> <span class="token punctuation">(</span> <span class="token class-name">Array</span> <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> slice <span class="token punctuation">)</span> <span class="token punctuation">;</span>