[Translation] JavaScript Fun Interview: What is functional programming?

原文地址 Medium - Master the JavaScript Interview: What is Functional Programming?

Functional programming in JavaScript field really has become a hot topic. Just a few years ago, a lot of JavaScript programmers do not even know what is functional programming, but in the past three years I have seen a large code base for each application are included in a large-scale functional programming ideas use.

Functional Programming (abbreviated FP) by a combination of pure function to build a software process, to avoid the state sharing , the variable data , and side effects generated. Functional programming is not a declarative programming imperative programming, the state of all application flows are pure functions. In contrast with the object-oriented programming is thought that the state of the application and are usually shared object method.

Functional programming is a programming paradigm , meaning that it is based on some basic way of thinking of the software architecture principles defined, Examples of other programming paradigms further comprising a process-oriented programming and object-oriented programming.

Compared imperative programming or object-oriented programming code tends to function more compact, more easily predictable test. But if you are not familiar with this way of or related to several common patterns of words, functional programming code can also look very compact and related documents for the novice may be more difficult to understand.

If you begin to search for terms related to functional programming, you may soon run into a wall, a lot of jargon can intimidate a novice. Simply discuss their learning curve a little too lightly, but if you've engaged in JavaScript programming for some time, then you should have used a lot of functional programming ideas or tools in your project.

Do not let new words to scare you. They will be easier than it sounds.

Which it can be said that the hardest part is to let a bunch of unfamiliar words filled your head up. Various terms look innocent, because before they master you also need to understand the meaning of these terms below:

  • Pure function
  • Function composition
  • Avoid sharing status
  • Avoid status change
  • Avoid the side effects

A pure function is defined as follows:

  • Each given the same input, its output is always the same
  • Without any side effects

Pure function of many features are important in functional programming, including references to transparency (if the expression can be replaced without changing its corresponding value of the program's behavior, the expression is called referential transparency).

Cited transparency that white is the same input always get the same output, which means that the function does not use any external state:

function plusOne(x) {
    return x + 1;
}
复制代码

The above example is the reference to transparency function, we can use 6 to replace plusOne(5)the function call. A detailed explanation can refer to stack overflow - What is referential transparency?

Combination function means that two or more functions are combined to produce a new function or performing the calculation process. For example combining function f.g( .sense refers to a composition ...) is equivalent to in JavaScript f(g(x)). Understand the function of a combination of functional programming to understand the use of writing software is a very important step.

State share

It means any state of the shared variables or objects in a shared memory space scope exists, or is used as an attribute of an object passed between scopes. The scope may include a shared or global scope closure scope. In object-oriented programming, objects are typically by adding an attribute to be among the other objects shared scope.

The problem is that the state share in order to understand the role of a function, you have to understand the past, each shared variables or effects used in the function.

Suppose you have a user object needs to be saved, your saveUser()function will initiate a request to the interface on the server. At the same time, users have had to replace the head of the operation, the call updateAvatar()to replace the head at the same time will trigger another saveUser()request. When you save, the server returns a standard user object that should replace any of the contents of memory to be synchronized with other API calls change or on the server response.

But here, the second response time to return earlier than the first. So when the first response (expired) returns, the new head is erased from memory, replaced back to the old head. This is a condition in contention example - is very common share related to a bug in the state.

Another state shared with frequently asked questions about the calling function is to change the order may cause a cascade failure, because the role of the state share in the function and timing-related:

// 在状态共享的函数中,函数调用的顺序会导致函数调用的结果的变化
const x = {
  val: 2
};

const x1 = () => x.val += 1;

const x2 = () => x.val *= 2;

x1();
x2();

console.log(x.val); // 6

// 同样的例子,改变调用顺序
const y = {
  val: 2
};

const y1 = () => y.val += 1;

const y2 = () => y.val *= 2;

y2();
y1();

// 改变了结果
console.log(y.val); // 5
复制代码

If we are to avoid sharing status, timing and sequence of function calls will not change the result of the function call. Pure functions, given the same inputs always get the same output. This makes a function call is completely independent, we can simplify and reconstruction fundamentally changed. Function somewhere to change, or the order of the function call does not affect or damage other parts of the program.

const x = {
  val: 2
};

const x1 = x => Object.assign({}, x, { val: x.val + 1});

const x2 = x => Object.assign({}, x, { val: x.val * 2});

console.log(x1(x2(x)).val); // 5

const y = {
  val: 2
};

// 由于不存在对外部变量的依赖
// 所以我们不需要不同的函数来操作不同的变量

// 此处故意留白


// 因为函数不变,所以我们可以以任意顺序调用这些函数任意次
// 而且还不改变其他函数调用的结果
x2(y);
x1(y);

console.log(x1(x2(y)).val); // 5
复制代码

In the example above, we use the Object.assign()method, and then passed into an empty object as the first parameter to copy xattributes, rather than changing in situ x. In this example, do not use Object.assign()it, it is equivalent to a simple scratch to create a new object, but this is to create a copy of the existing state of transformation in JavaScript instead of using the common model, we demonstrated that in the first example.

If you carefully read this example console.log()sentence, you should note that I have already mentioned some of the things: function composition. Recall that before the said knowledge, combined function looks like this: f(g(x)). In this case x1(x2()), that is x1.x2.

Of course, if you change the order of the combined output will also change. The execution order is still important. f(g(x))Not always equivalent to g(f(x)), but no longer have to worry about a thing variables outside the function, which is a big deal. In the non-pure function, a function can not be completely aware of what has been done, the entire history of each variable unless you know the function or use of influence.

Remove timing-dependent function calls, you will completely rule out this type of bug.

Immutability

Immutable objects means that once an object is created can no longer be modified. That is contrary mutable object can be modified after the object is created. Immutability is a core concept of functional programming, because without this feature, data flow program will be lost, the loss of state history, then your program will always emerge a strange bug.

In JavaScript, do not put constand invariance confused. constBound after a creation can no longer be assigned to a variable name. constDo not create immutable objects. Use constvariables created can no longer be assigned but can modify the properties of an object.

Is completely immutable object can not be modified. You can deep freeze an object so that it becomes True immutable values. JavaScript has a method to freeze an object in the first layer:

const a = Object.freeze({
  foo: 'Hello',
  bar: 'world',
  baz: '!'
});

a.foo = 'Goodbye';// Error: Cannot assign to read only property 'foo' of object Object
复制代码

This is the only way to freeze shallow immutable, such as:

const a = Object.freeze({
  foo: { greeting: 'Hello' },
  bar: 'world',
  baz: '!'
});

a.foo.greeting = 'Goodbye';

console.log(`${ a.foo.greeting }, ${ a.bar }${a.baz}`);// Goodbye world!
复制代码

We can see, the original property is a frozen top layer is immutable. However, if the object attribute value, then the object is still variable (including arrays, etc.). Unless you traverse the entire object tree, it will freeze the layers.

In many functional programming languages ​​are immutable and special data structure called a search tree data structure, such data structure can be effectively freezing depth.

Find a tree by a structure shared by a reference to the shared memory space, which is after the object is copied remains unchanged, thus saving memory, making the performance of certain types of operations have significantly improved.

For example, you can compare the use of identity controls at the root of an object tree. If the identity of the same, if the identity of the same, then you will not have to traverse the whole tree pieces to compare the differences.

There are some relatively good use of the library tree in JavaScript, such as Immutable.jsand Mori.

Maybe the library I have used, I prefer to use in large-scale projects need a lot of immutable state of Immutable.js.

side effect

Refers to the side effect when the function call, the function returns a value other than in addition, also produce additional effects on the main calling function. Not just a function of the side effects of returns a value, but also do other things:

  • Changing the external object or variable attributes (or global variables parent scope chain variable function)
  • Print the output in the console
  • I wrote something to the screen
  • I wrote something to the file
  • I wrote something to the network
  • Trigger external process
  • Call other functions have side effects

Side effects in functional programming most of the time are to be avoided, so as to make clear the role of the program, they are also more likely to be tested.

HaskellOther programming languages ​​Monads always use the side effects from a purely function independently and packaged. Monads too much about the content, you can go to find out.

But you need to know right now is that the side effects need to conduct separate from your software out, so that your software is easier to expansion, remodeling, debug, test, and maintain.

This is the most front-end framework to encourage users to separate administrative status and rendering components, decoupling module.

Improve reusability by higher-order functions

Functional programming tended complex series of functions to process the data with tools. Object-oriented programming methods and tend to data on the subject, these methods can be used to merge operation that is designed to good data, often contained in a particular component or instance.

In functional programming, any type of data are the same position, the same map()function can traverse the object, a string, number, or any type of data because it receives a function as a parameter, and this parameter can function properly handled to given data type. This programming function is achieved by the higher order function characteristic.

JavaScript functions are first-class citizens uphold the view that allows us to treat functions as data - to assign function to a variable, the function passed to other functions, functions, and so let the function return ...

Higher order function refers to the function may receive any parameter as a function of a function or return function, or both. Higher-order functions are often used:

  • Abstract or independent operation of the flow control asynchronous callback, promises ,, monads and so on ...
  • Create a utility function can handle a variety of data types
  • Some parameters or functions used in a multiplexed or combined function created object currying function
  • Receiving a set of parameters as a function of some of them and then returns as a combination

Container, functor, lists, flow

Functor is a kind of thing that can be mapped. In other words, it is a container interface, the interface can be used applyto value inside a function (translated phrase too strange, skill is not enough. Original it's a container which has an interface which can be used to apply a function to the values inside it.) .

Earlier we know the same map()function can be performed on multiple data types. It is through the mapping operation to enhance the use of functors API to achieve. The key flow control operation by map()using the interface function. If this is Array.prototype.map()the case, the container is an array, other data structures may functor as long as they provide the map()API.

Let's look at Array.prototype.map()how to allow abstract data type from the mapping function so that map()the function can be used on any type of data. We create a double()function to map the incoming parameters multiplied by 2 operation:

const double = n => n * 2;
const doubleMap = numbers => numbers.map(double);
console.log(doubleMap([2, 3, 4])); // [ 4, 6, 8 ]
复制代码

If we want to target to a game operation, let the score get to double it? Only you need to double()pass the function map()a little change to the value of:

const double = n => n.points * 2;

const doubleMap = numbers => numbers.map(double);

console.log(doubleMap([
  { name: 'ball', points: 2 },
  { name: 'coin', points: 3 },
  { name: 'candy', points: 4}
])); // [ 4, 6, 8 ]
复制代码

The concept of using a functor / higher order function to use the native data types of different function tool is important to functional programming operation. A similar concept is applied All sorts of Different Ways .

List in time is the continuation of the flow.

You just need to know the only way arrays, and functions are not applied in container and container value. For example, an array is a set of data. List in time is the continuation of the flow - so you can use the same tool function to handle incoming event streams - you will have experience of this practice in the future functional programming.

Declarative Programming & imperative programming

Functional programming is a declarative programming paradigm, the logic control flow is not explicitly described, when expressed.

Imperative programming code line by line will be described with particular steps to achieve the desired results. The flow control is simply not care what?

Declarative programming abstractions flow control process, use the code to describe the data flow how to do, how to get abstract way.

The following example shows the mapping imperative programming digital array and returns the value returned by the new array 2:

const doubleMap = numbers => {
  const doubled = [];
  for (let i = 0; i < numbers.length; i++) {
    doubled.push(numbers[i] * 2);
  }
  return doubled;
};

console.log(doubleMap([2, 3, 4])); // [4, 6, 8]
复制代码

Declarative programming to do the same thing, but using function tool Array.prototype.map()abstract way flow control, allowing you to make a clearer expression of the data stream:

const doubleMap = numbers => numbers.map(n => n * 2);

console.log(doubleMap([2, 3, 4])); // [4, 6, 8]
复制代码

Statement imperative programming is often used, i.e. a period perform an action statement code, including for, if, switch, throwand the like.

Declarative programming code is more dependent expression, the expression is a piece of code have a return value. Examples of the following expressions:

2 * 2
doubleMap([2, 3, 4])
Math.max(4, 3, 2)
复制代码

You will often see an expression is assigned to a variable, the function returns an expression or a function is passed in the code.

in conclusion

This article points:

  • Function uses a shared function rather than a pure state or side effects of
  • To carry forward the immutability rather than Variable Data
  • Using the flow control function of the composition and not imperative
  • Many native, utility functions can be multiplexed can be applied to many types of data by higher order functions, not only the specified data processing
  • Declarative programming rather than imperative programming (you know what to do, not how to do)
  • Expressions and statements
  • Comparative & vessel higher order function of the ad hoc polymorphism

reference

What is the Monad (Functional Programming)? Functor in the end is what? ApplicativeMonad

Guess you like

Origin blog.csdn.net/weixin_33843947/article/details/91391172