We're planting a tree for every job application! Click here to learn more

The Most Clever Line of JavaScript

Seva Zaikov

2 Mar 2018

3 min read

The Most Clever Line of JavaScript
  • JavaScript

Recently my friend sent me a very interesting JS snippet, which he found in one open-source library:

addressParts.map(Function.prototype.call, String.prototype.trim);

At first, I laughed and thought “nice try”. Second thought was that map accepts only one argument, and I went to MDN docs, where I realized that you can pass context as a second argument. At this point I was really puzzled, and after running my confusion increased to the limit – it worked as expected!

I’ve spent at least half an hour playing with it, and it was an interesting example how magical JavaScript can be, even after years spent writing it. Feel free to figure it out by yourself, and if you want to check out my understanding, keep reading!

So, how does it work? Let’s start with super naive implementation (which is actually shorter and easier to read :)):

addressParts.map(str => str.trim());

But as it is clear, we strive here to avoid creating new functions, so let’s move on. Function.prototype.call is a function in prototype of all JavaScript functions, and it invokes function, using first argument as this argument, passing rest arguments as parameters of function invocation. To illustrate:

// this function has `Function` in prototype chain
// so `call` is available
function multiply(x, y) {
  return x * y;
}

multiply.call(null, 3, 5); // 15
multiply(3, 5); // same, 15

Typical usage of the second argument can be the following – imagine you have a class-based react component, and you want to render list of buttons:

class ExampleComponent extends Component {
  renderButton({ title, name }) {
    // without proper `this` it will fail
    const { isActive } = this.props;
    return (
      <Button key={title} title={title}>
        {name}
      </Button>
    );
  }

  render() {
    const { buttons } = this.props;

    // without second param our function won't be able
    // to access `this` inside
    const buttonsMarkup = buttons.map(this.renderButton, this);
  }
}

However, from my experience, it is not that common to use this second argument, usually class properties or decorators are used to avoid binding all the time.

There is one similar method – Function.prototype.apply, which works the same, except that the second argument should be an array, which will be transformed to a normal list of arguments, separated by comma. So, let’s see how we can use it to calculate maximum:

Math.max(1, 2, 3); // if we know all numbers upfront
// we can call it like that

Math.max([1, 2, 3]); // won't work!

Math.max.apply(null, [1, 2, 3]); // will work!

// however, ES2015 array destructuring works as well:
Math.max(...[1, 2, 3]);

Now, let’s try to recreate a call which will solve our problem. We want to trim the string, and it is a method in String.prototype, so we call it using . notation (however, strings are primitives, but when we call methods, they are converted to objects internally). Let’s go back to our console:

// let's try to imagine how trim method is implemented
// on String.prototype
String.prototype.trim = function() {
  // string itself is contained inside `this`!
  const str = this;
  // this is a very naive implementation
  return str.replace(/(^\s+)|(\s+$)/g, '');
};

// let's try to use `.call` method to invoke `trim`
" aa ".trim.call(thisArg);

// but `this` is our string itself!
// so, next two calls are equivalent:
" aa ".trim.call(" aa ");
String.prototype.trim.call(" aa ");

We are now one step closer, but still not yet there to understand our initial snippet:

addressParts.map(Function.prototype.call, String.prototype.trim);

Let’s try to implement Function.prototype.call itself:

Function.prototype.call = function(thisArg, ...args) {
  // `this` in our case is actually our function!
  const fn = this;

  // also, pretty naive implementation
  return fn.bind(thisArg)(...args);
};

So, now we can put all pieces together. When we declare function inside the .map, we pass Function.prototype.call with bound <String.prototype.trim> as this context, and then we invoke this function on each element in the collection, passing each string as thisArg to the call. It means that String.prototype.trim will be invoked using string as this context! We already found that it will work, using our example:

String.prototype.trim.call(" aa "); // "aa"

Problem solved! However, I think it is not the best example how one should write such a code in JavaScript, and instead just pass a simple anonymous function:

addressParts.map(str => str.trim()); // same effect

If you’re passionate about Front End development, check out the JavaScript Works job-board here!

Did you like this article?

Seva Zaikov

Self-taught programmer, with a big passion to learn

See other articles by Seva

Related jobs

See all

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Related articles

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

12 Sep 2021

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

12 Sep 2021

WorksHub

CareersCompaniesSitemapFunctional WorksBlockchain WorksJavaScript WorksAI WorksGolang WorksJava WorksPython WorksRemote Works
hello@works-hub.com

Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ

108 E 16th Street, New York, NY 10003

Subscribe to our newsletter

Join over 111,000 others and get access to exclusive content, job opportunities and more!

© 2024 WorksHub

Privacy PolicyDeveloped by WorksHub