7 ms·
JavaScript: Function Invocation Patterns
- hafabnew 14y agoThere's an error in his first 'Function Invocation' example, the answer is 500, not 501. [Reason: 'this.value++;' in the method invocation refers to obj.value, since 'this' is bound to 'obj'. Only in the innerFunction function invocation does 'this' bind to the global object.]
- deleted 14y ago[deleted]
- user24 14y agoShould have mentioned call along with apply. Not sure these are patterns rather than just language features.
- cjfont 14y agoI agree, this is similar to saying that i+=1 and i++ are increment patterns.
- andrewflnr 14y agoWell, yes, except complicated enough to merit more explanation.
- bengillies 14y agoExactly. Stuff that's built directly into the language isn't a pattern, it's a feature (perhaps a wart in this case). From Wikipedia [1]: In software engineering, a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. A design pattern is not a finished design that can be transformed directly into source or machine code. It is a description or template for how to solve a problem that can be used in many different situations. Patterns are formalized best practices that the programmer must implement themselves in the application. [1] http://en.wikipedia.org/wiki/Software_design_pattern http://en.wikipedia.org/wiki/Software_design_pattern
- franze 14y agoplease see the HN guidelines http://ycombinator.com/newsguidelines.html http://ycombinator.com/newsguidelines.html Please don't do things to make titles stand out, like using uppercase or exclamation points, or adding a parenthetical remark saying how great an article is. It's implicit in submitting something that you think it's important. plus i have a very strong distain about anyone or anything (i.e. headlines) which tell me what i MUST do / know / think... - also the article above is about a very basic language feature of JS that hopefully anyone who has every touched JS already knows about.
- camus 14y agoI agree this article is kind of javascript 101. And it doesnt do a great job explaining exactly why things are the way they are in javascript. And these are not patterns , since they are built in the language. It would be like saying using the world class in java is using a pattern... I dont see the point featuring it on HN...
- raganwald 14y agoAmusingly, the original title has a spelling mistake: "Javascript: Function Inovcation Patterns." But enough burying the lede. The issue I have with this title is simple: It's not clear WHY I must know these patterns: The focus of the post is not why I must know them, but rather This post explains the four patterns, how to use them and what to watch out for. Had the post kicked off by explaining that not knowing one or more of these patterns could lead to disaster, I'd be onside with the submission title rewrite (sans emphasis).
- deleted 14y ago[deleted]
- fatboy 14y agoNot using Javascript frequently enough to justify reading a book on it, I found the article useful. These features have been counterintuitive for me.
- dsego 14y agoKatz has an interesting article on this as well: http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/ http://yehudakatz.com/2011/08/11/understanding-javascript-fu...
- dnc 14y agoOne portion of Douglas Crockford's book "JavaScript: The Good Parts" describes invocation patterns thoroughly. It might be that the author of the post was inspired by this book. Since he hasn't mentioned it, I did it in case someone wants to know more about the topic (and doesn't know about the book).
- jszen 14y agoHe does actually refer to Crockfords book roughly half way through.
- dnc 14y agoNope, he doesn't. :)
- davesims 14y agoHe does, but it's indirect. In the article he says: "There is a remedy which was championed by Douglas Crockford: Augment Object with a create method that accomplishes what the constructor invocation pattern tries to do." That sentence contains a link to another page on OP's site which at the top says "Douglas Crockford's wonderful book JavaScript: The Good Parts does a fanastic job of explaining this topic, and I urge the interested reader to buy his book."
- dnc 14y agoThanks for pointing it out. I didn't see it. Your comment motivated me to look at the whole post about JavaScript prototypes again and read it. It is very good, I refreshed my knowledge about Object.prototype, Function.prototype design.
- willvarfar 14y agoThe big bug as I see it is: obj = { get_name = function() { return "I am an object" }, func = function() { alert(this.get_name()); } } This looks dandy, and obj.func() works as expected. but if you pass obj.func as a callback, the this when its invoked will be some other object (by default, the window object): button.onclick = obj.func; // bang when invoked The number of times I got screwed by that. You end up having to have little anonymous functions for all callbacks: button.onclick = function(evt) { obj.func(); } (apologies for bugs; just typing javascript from memory) (would love to be wrong)
- locci 14y agobind was introduced in ES5 (and previously in most libraries) to fix this https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind https://developer.mozilla.org/en-US/docs/JavaScript/Referenc...
- huskyr 14y agoAnd trivially easy to shim for older browsers. I would really recommend using Function.prototype.bind instead of the 'var self = this' or library bind functions (such as $.proxy), it's just the way it should be written :)
- jessaustin 14y agoTo confirm my understanding, would the erroneous line from the comment above be rewritten like: button.onclick = obj.func.bind(obj); So un-DRY! It's almost admirable, how blatant a hack this is.
- politician 14y agoIt clicked for me when I decided that there were no methods and considered all function invocations to be special cases of `apply`. Then the case you mentioned becomes a bog standard case of a property lookup, and the callback becomes a case of `apply(window, [args])`. tldr: JavaScript has functions, not methods :)
- 14y ago
- FuzzyDunlop 14y agoThere is an easy way to get round this problem, but it is in my opinion a hack. One gets around this problem by assigning a varialbe (by convention, it is named that) to this inside the function Or use `bind` instead.
- emehrkay 14y agoor use call or apply when invoking innerFunction, which he describes later in the article
- TazeTSchnitzel 14y agoNo mention of strict mode? Come on! 'use strict' makes the this variable undefined in functions invocation.
- recursive 14y agoI have yet to find a use for constructors in a real world problem. I've been able to do anything I ever wanted to with object literals. I'm not sure why there is so much emphasis placed on object prototypes.
- jlongster 14y agoHe's wrong in the "Constructor Invocation" example. function Foo(type) { this.type = type; return type; } var bar = new Foo(5); `bar` DOES equal 5. When you return something in a constructor, it returns it instead of returning the newly constructed object. This is a neat way for constructing different types of things. And most of his complaints are just because he doesn't understand how `this` scoping works in javascript. If you don't understand something, don't just blame it on "bad patterns". It might not be the most intuitive, but once you learn it, it's fine. Sure, I have to bind `this` to a different function here and there, but these problems are not that bad in real world javascript.
- lhorie 14y ago> `bar` DOES equal 5 No, it doesn't. Javascript is a bit weird when it comes to return statements inside constructors. `bar` will be equal to `type` only if `(type instanceof Object) == true`. Otherwise, it will be a new object. function Foo(type) { this.type = type; return type; } console.log(new Foo(/a/)); // Regexp /a/ console.log(new Foo("a")); // {type: "a"} console.log(new Foo(5)); // {type: 5} console.log(new Foo([1,2])); // [1,2] console.log(new Foo({a:1})); // {a: 1}
- jlongster 14y agoHuh, you're right. I thought I typed that at the REPL and it gave back 5, but obviously I typed the wrong thing. Almost all cases that I've used this functionality have been to return a different object. I suppose when you say "new" you're supposed to expect an object, which is why it works that way.
- ynniv 14y agoa good time to point out that calling Object() without "new" returns a new object. This is often unexpected when creating inheritance schemes that chain the parent constructor. https://github.com/documentcloud/backbone/pull/1269 https://github.com/documentcloud/backbone/pull/1269
- 14y ago
- taybin 14y agoAlso makes for a good interview question.
- bazsouthafrica 14y agoHi Guys I just want to give you some feedbacks in the comments (I am the author of this article). Firstly, with regards to the title, I did not read the newsguidlines document - I have submitted links in the way and style that other people did. For sure, in the future, I will follow these guidlines, but this must be a huge problem as lots of people do this. Secondly, these are patterns (not language features). Yes, I was inspired by Douglas Crockford's book where he describes this as patterns. To me describing them as patterns makes sense: For instance, there is really nothing different about calling a method and a function. If you have to make a difference, then it is a pattern. And because putting new in front of a function also calls that function, it is in my mind a pattern. And in that sense, so is apply. But I welcome the debate, and thanks for the constructive comments. I will take all these comments into consideration the next time I submit something.
- meanJim 14y agoFor learning more about JavaScript it was a great read.
- robocat 14y agoNice article. I think you are missing a fifth way to call a function, a property accessor function (although I have never used one, so not certain!). Some mention of how somefunc.bind(someobj) affects the "patterns" might also be worthwhile (although maybe confusing!).
- rgbrgb 14y ago> Invoking a function suspends execution of the current function, passing controls and parameters to the invoked function. False. JS functions execute asynchronously, without suspending the execution of the current function.
- rgbrgb 14y agoDid I miss something here? Why was this downvoted?
- bazsouthafrica 14y agoHi I did not downvote your comment, but it is fundamentally incorrect. If your JavaScript program has been designed well, then asynchronisity by using an event driven model is the way to go. But that is very different to what I said about functions stopping the execution of the current function. This is true. For example var func1 = function() { //Execute something here } var func2 = function() { //Execute something here func1(); //Stop execution of this function, and rather execute func2 //Execute something here } I hope the above explains this a bit better.