1

I read this blog post recently: The Two Pillars of JavaScript Part 1: How to Escape the 7th Circle of Hell, which is essentially a criticism of object oriented programming, and advocacy for funtional programming instead.

Some key points made:

  • Constructors violate the open/closed principle because they couple all callers to the details of how your object gets instantiated. ... JavaScript doesn’t need constructor functions because any function can return a new object. With dynamic object extension, object literals and Object.create(), we have everything we need — with none of the mess. And this behaves just like it does in any other function. Hurray!

  • Classical Inheritance generally lets you inherit only from a single ancestor, forcing you into awkward taxonomies. I say awkward because without fail, every OO design taxonomy I have ever seen in a large application was eventually wrong.

  • The coupling between a child class and its parent is the tightest form of coupling in OO design. That’s the opposite of reusable, modular code.

    Making small changes to a class creates rippling side-effects that break things that should be completely unrelated.

Ok, sure. Without discussing the merits of these arguments (I think the article could do with some code examples) - how is this functional/prototype hacking paradigm used in practise?

ie. Particularly in regards to a framework like Angular or React - where the foundation of components are ES6 classes that extend a framework parent class.

  • 2
    You might be interested in React's 'stateless functional components'. I can't comment on Angular. – jasonk Sep 6 '18 at 4:06
  • @jasonk Sure - React has stateless functional components, but it's hard to know how you would create a button that knows how many times it has been clicked with it. – dwjohnston Sep 6 '18 at 4:20
  • see Discuss this ${blog} – gnat Sep 6 '18 at 9:52
  • you'll have to find some functional programming advocates..... – Ewan Sep 6 '18 at 12:36
  • @dwjohnston, you cite Classical Inheritance, but JavaScript inheritance works on prototypal inheritance which works a bit differently than classic inheritance. – Daniel Nov 24 '18 at 19:17
2

In my previous role we were using mostly pure functions in React. Remember that React is a "library for building user interfaces". Often I see React projects where components are very object-oriented and encapsulate state, behavior, UI, and even style. There is a tradeoff to be made. When you encapsulate all those things in the component, you arguably get better readability, but you lose flexibility, reusability, testability, and loose coupling.

For starters I recommend you separate all behavior out of React components and inject the behavior through component properties. You can then define all your behavior as pure functions as well--even stateful behavior. Check out Recompose for a bunch of higher-order components that help keep functional when dealing with component state and Redux for application state.

As a concrete example, let's consider a button that increments a counter. With object-oriented components, you might write something like:

class Counter extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      counter: 0,
    }
  }

  render() {
    const {
      counter,
    } = this.state

    const onClick = () => {
      this.setState({
        counter: counter + 1,
      })
    }

    return (
      <button onClick={onClick}>Val {counter} click to increase</button>
    )
  }
}

With functional programming we would write it like so:

// pure functional component
const Counter = ({
  onClick,
  counter,
}) => (
  <button onClick={onClick}>Val {counter} click to increase</button>
)


// elsewhere define the behavior again as pure functions
const FunctionalCounter = Recompose.withStateHandlers({
  counter: 0, // our initial state
}, {
  onClick: ({ counter }) => () => ({ // a pure function that takes state, props, and parameters and updates state
    counter: counter + 1,
  }),
})(Counter)

Angular is a completely different beast because it's not a UI library, it's a "front-end web application framework" and it imposes a lot of constraints on how you write your applications. I'm unfamiliar with how one would write an Angular application with functional programming, but you can apply the same principles that I've done with React. Specifically, separate your behavior and business logic out of the UI into thoughtfully organized functions that are injected into the UI (i.e. you could use Angular's dependency injection to inject your business logic functions). It's generally a good idea to do this anyway so that your application logic is not coupled to a UI framework.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.