Hacker News new | ask | show | jobs
by jongar_xyz 3478 days ago
> #2: Goal: To be able to understand this function: > > // The .bind method from Prototype.js > Function.prototype.bind = function(){ > var fn = this, args = > Array.prototype.slice.call(arguments), object = args.shift(); > return function(){ > return fn.apply(object, > args.concat(Array.prototype.slice.call(arguments))); > }; > }

I do not want to understand this absurdness. I want a comment that tells me what it does so I can rewrite it in a sane way.

8 comments

Do you really think it's good practice to use comments to describe how the language itself works? It's not like you can't find comprehensive, quality documentation for every single thing that happens in that function on MDN or equivalent.

Is that function that insane? I can understand it at a glance, and performance is high (it matters here). AS a JS programmer, just knowing that it is an implementation of bind() should be enough of a hint that it uses its first argument as context, the rest as a curry and the arguments of the newly generated function as additional arguments.

To be fair, the syntax of the variable initialization could be separated into 3 lines for better clarity.
This is a perfectly straightforward implementation of a somewhat sophisticated concept.

But one wouldn't encounter this code in an application; this is library code. It's so useful and common that it's part of the ES5 standard (yes, ES5, not ES6). It might be the bind method from Prototype.js, but it's also the .bind method that all ES5 JS functions have.

Anyway, the question is not whether or not you should/coudl write this. The question is whether or not it's a good goal to be able to read this.

IMO, anyone who cannot read this function, albeit slowly and carefully, isn't an intermediate JS programmer, much less an advanced one.

Which of the concepts in this chunk of code is foreign to you? Prototypes? this? Using Array.p.s.c() to turn array-like args into an actual Array? shift? returning a function that, when called, invokes another function on the concatenation of one set of args with another set of args? This is all easy-mode stuff, unless you're brand new to JS, or you haven't bothered learning it.

I learned about all of this stuff by doing challenges on codewars.com
The post is about learning advanced JavaScript, if you don't want to understand that then the post isn't for you, (not that there's anything wrong with that). There may not be a more sane way to write this, (in es5).
I would make 3 changes.

Separate the declaration to 3 lines because the 2nd and the 3rd declarations depend on each other. Keeping them on the same line makes the reader think this is a simply declarative code but in fact it's the opposite.

Avoid using the slice shift combo but use slice with a start of 1 plus direct index access to the arguments[0] to get the first argument. this way i'm not mutating the args array and that makes the code easier to follow.

Rename the object variable to '_this'. Giving the reader a hint as to what it is used for.

And of course if this is actually to be used in production I assume it will be wrapped inside a check to see if the bind function is already defined.

Hint: to write code in HN comments indent anything you write by at least two spaces. Result (long lines split - people on mobile may still have to scroll horizontally):

  // The .bind method from Prototype.js
  Function.prototype.bind = function(){
    var fn = this,
        args = Array.prototype.slice.call(arguments),
        object = args.shift();

    return function(){
      return fn.apply(
        object,
        args.concat(Array.prototype.slice.call(arguments))
      );
    };
  }
What's a more sane way to write that? It seems fairly straightforward to me, although ES6 might clean up the syntax a bit.
> I do not want to understand this absurdness.

Then don't read the ejohn? =)

(Me neither, fwiw. Would rather write a combined com/transpiler from sane to asm.js/wasm bypassing JS entirely. Not that I do, just that I'd rather.)

When you start using ES6, a lot of this garbage tends to disappear, if that helps. It infuriates me to see this kind of code, also. ES6 is a real godsend, dude! Fuck, I basically just said what everyone else here said. Well, whatever!