JavaScript: Function Invocation Patterns
doctrina.org
doctrina.org
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.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).
Hopefully, yes, but I think reality is much more depressing than that. Unfortunately, the JavaScript programmers that don't know probably don't read Hacker News either.
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).
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."
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.
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}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.
IMHO the return value of calling `Object()` without parameters is exactly what one would expect. Calling it w/ parameters is what I think causes surprising behavior
var x = {a: 2}
console.log(x === x) // true
console.log(Object(x) === x) // true
console.log(new Object(x) === x) // true
For the `Object.call(x)` case, I'd expect it to return a new object (and not x), for the same reason I'd expect [].slice.call(arguments) to return a new array (and not arguments). window.test = 2
var b = Object.call(window) //this is the same as `var b = window.Object()` and therefore the same as `var b = Object()`
assert(b.test == 2) //why should this be true?Scoping: Javascript uses C/Java notation but it does not have block scope, only function scope. That to me seems very misleading.
And with regards to `this`, the way function invocation sets `this` differs totally from method invocation. How can this not be a problem!
Yes, it is, but we weren't talking about that problem. That is already solved in ES6 with `let`, which is approved and will be available in about a year.
> And with regards to `this`, the way function invocation sets `this` differs totally from method invocation. How can this not be a problem!
Function and method invocation are different things, with different semantics. It's like that in many other languages too. Sure, the way `this` is handles is a problem sometimes, but I think it's overblown.
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.
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!).
Or use `bind` instead.
Not sure these are patterns rather than just language features.
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.
[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.]
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)
tldr: JavaScript has functions, not methods :)
I do however intend to use an example similar to the one you have presented when I cover closures and scoping in JavaScript.
https://developer.mozilla.org/en-US/docs/JavaScript/Referenc...
button.onclick = obj.func.bind(obj);
So un-DRY! It's almost admirable, how blatant a hack this is.'use strict' makes the this variable undefined in functions invocation.
False. JS functions execute asynchronously, without suspending the execution of the current function.
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.