Modern JS Concepts
Pure Functions
A pure function's return value is determined only by its input values (arguments) with no side effects.
function half(x) {
return x / 2;
}
half(8) === 4
Referential transparency
Pure Functions
Pure functions must take arguments.
The same input (arguments) will always produce the same output (return).
Pure functions rely only on local state and do not mutate external state (note: console.log changes global state).
Pure functions do not produce side effects.
Pure functions cannot call impure functions.
Impure Functions
An impure function mutates state outside its scope. Any function that has side effects is impure.
// impure function producing a side effect
function showAlert() {
alert('This is a side effect!');
}
// impure function mutating external state
var globalVal = 1;
function incrementGlobalVal(x) {
globalVal += x;
}
// impure function that resembles a pure function,
// but returns different results given the same inputs
function getRandomRange(min, max) {
return Math.random() * (max - min) + min;
}
Purity Takeaways
impure functions that procedurally invoke pure functions.
advantages for testing and immutability
Referential transparency enables memoization
It can be a challenge to determine when functions are truly pure.
State
State refers to the information a program has access to and can operate on at a point in time.
Stateful
Stateful programs, apps, or components store data in memory about the current state. They can modify the state as well as access its history.
var number = 1;
function increment() {
return number++;
}
increment();
Stateless
Stateless functions or components perform tasks as though running them for the first time, every time. This means they do not reference or utilize any information from earlier in their execution.
var number = 1;
function increment(n) {
return n + 1;
}
increment(number);
State Takeaways
State management is important for any complex application.
Stateful functions or components modify state and store history, but are more difficult to test and debug.
A stateless program returns new state rather than modifying existing state.
Immutability
If an object is immutable, its value cannot be modified after creation.
In JavaScript, strings and number literals are immutable by design.
Mutable
If an object is mutable, its value can be modified after creation.
Objects are mutable by design.
Immutability in JavaScript
JavaScript objects can also be frozen with Object.freeze(obj) to make them immutable.
shallow
we can return a new state object each time the object changes.
deep-freeze
immutable.js
Immutability Takeaways
Immutability results in code that is simpler to reason about.
many algorithms and operations cannot be implemented efficiently.
Immutability enables persistency.
Imperative and Declarative
JavaScript can support both programming paradigms.
Imperative programming describes how a program's logic works in explicit commands with statements that modify the program state. eg. for
Declarative programming describes what a program's logic accomplishes withoutdescribing how. eg. Array.each
Imperative and Declarative Programming Takeaways
Declarative programming has obvious advantages with regard to brevity and readability, but at the same time it can feel magical.
Higher-order Functions
A higher-order function is a function that:
accepts another function as an argument,
or
returns a function as a result.
Functional Programming
Functional programming encompasses the above concepts in the following ways:
Core functionality is implemented using pure functions without side effects.
Data is immutable.
Functional programs are stateless.
Imperative container code manages side effects and executes declarative, pure core code.
const fpCopy = `Functional programming is powerful and enjoyable to write. It's very cool!`;
// remove punctuation from string
const stripPunctuation = (str) =>
str.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, '');
// split passed string on spaces to create an array
const getArr = (str) =>
str.split(' ');
// count items in the passed array
const getWordCount = (arr) =>
arr.length;
// find items in the passed array longer than 5 characters
// make items lower case
const getKeywords = (arr) =>
arr
.filter(item => item.length > 5)
.map(item => item.toLowerCase());
// process copy to prep the string, create an array, count words, and get keywords
function processCopy(str, prepFn, arrFn, countFn, kwFn) {
const copyArray = arrFn(prepFn(str));
console.log(`Word count: ${countFn(copyArray)}`);
console.log(`Keywords: ${kwFn(copyArray)}`);
}
processCopy(fpCopy, stripPunctuation, getArr, getWordCount, getKeywords);
Functional Programming Takeaways
Immutable data and statelessness mean that the program's existing state is not modified. Instead, new values are returned.
Pure functions are used for core functionality. In order to implement the program and handle necessary side effects, impure functions can call pure functions imperatively.
Observables
subscribe to observables and react to events emitted by streams
Observables example
const resize$ =
Rx.Observable
.fromEvent(window, 'resize')
.throttleTime(350);
const subscription =
resize$.subscribe((event) => {
let t = event.target;
console.log(`${t.innerWidth}px x ${t.innerHeight}px`);
});
Resizing the browser window emits a stream of events over a period of time as the window is dragged to its desired size. We can create an observable and subscribe to it to react to the stream of resize events
Hot Observables
User interface events are hot.
Hot Observables will always push even if we're not specifically reacting to them with a subscription.
Cold Observables
cold Observables begins pushing only when we subscribe to it. If we subscribe again, it will start over.
const source$ = Rx.Observable.range(1, 5);
// subscribe to source$ observable
const subscription = source$.subscribe(
(value) => { console.log(`Next: ${value}`); }, // onNext
(event) => { console.log(`Error: ${event}`); }, // onError
() => { console.log('Completed!'); } // onCompleted
);
Observables Takeaways
Observables are streams. We can observe any stream
Reactive Programming
Reactive programming is concerned with propagating and responding to incoming events over time, declaratively (describing what to do rather than how).
Reactive Programming with JavaScript
<input id="confirmation-code" type="text">
<p>
<strong>Valid code attempt:</strong>
<code id="attempted-code"></code>
</p>
const confCodeInput = document.getElementById('confirmation-code');
const attemptedCode = document.getElementById('attempted-code');
const confCodes$ =
Rx.Observable
.fromEvent(confCodeInput, 'input')
.map(e => e.target.value)
.filter(code => code.length === 6);
const subscription = confCodes$.subscribe(
(value) => attemptedCode.innerText = value,
(event) => { console.warn(`Error: ${event}`); },
() => { console.info('Completed!'); }
);
Reactive Programming Takeaways
The reactive programming paradigm involves observing and reacting to events in asynchronous data streams.
deck
By Joson Chen
deck
- 218