Is this:
(function(a) {
return 3;
})(this);
equivalent to:
(function() {
return 3;
})();
If there are any differences, please explain
Here's the difference I think you're looking for: the second example has access to the outer this (through the a variable), while the second example does not.
Normally, you don't need to pass in arguments to an IIFE (although you certainly can, to get more readable or modular code), because newly-declared functions have access to their outer scope variables:
var foobar = 5;
(function() {
// I can use the outer-scope `foobar` in here!
})();
However, this is an exceptional case, because the newly-created function will have its own this that will shadow the outer this:
// outer here, `this` is one thing
(function() {
// in here, `this` might be something else
// because each new functions invocation sets `this` within the function
})();
You can see shadowing behavior with non-this variables like this:
var foobar = 5;
(function() {
var foobar = 7;
// I can't use the outer-scope `foobar`
// because it is shadowed by local-scope `foobar`
})();
A similar thing happens with this. In my foobar example, the shadowing was done explicitly, but with this, the shadowing always happens, because each function gets a new local-scope this.
You can access the outer this by aliasing it a new name, done here by formal argument:
// outer here, `this` is one thing
(function(outerThis) {
// in here, `this` might be something else
// but `outerThis` refers to the outer `this`
})(this);
If you don't alias the outer this to a new name, you will not have access to it, because it will be shadowed by local this. Note that you can also alias your outer this to another outer-scope variable, like:
var outerThis = this;
(function() {
// we can access the outer-scope `outerThis` because it is not shadowed
})();
Well, the first you're passing an argument to, but it is never used. However, the functionality is the same for both. The second is slightly faster, due to not passing an argument for no reason, assuming this isn't just optimized away.
It depends on how you define equivalent.
If you define it in terms of what the functions actually do, then, yes, they are equivalent. Although, of course, this is only true for their current content. One difference is that the first one has access to the outer this, while the second one doesn't - although this does not matter in your example.
Regarding to your comment whether just passing this makes a difference here: No, it does not.
If you define equivalent in a different way, then the functions may be different, e.g. when defining equivalent as having the same arity.
I guess the obvious counter-question would be what's the use case behind your question: Why do you ask this? (If it's not just out of curiosity and for academical reasons.)
Related
I am trying to sharpen my JavaScript skills and I am aware that there are four basic ways to invoke a function - which alter the way this is defined. The two I am interested in are the basic two:
Invocation as a function
Invocation as a method
Which is fine. The first, this will refer to the window object:
function doSomething() {
console.log(this);
}
doSomething(); // window is logged
And the second this will refer to the object it is being executed from within:
var t = {
doSomething: function () {
console.log(this);
}
};
t.doSomething(); // t is logged
Which is all fine. However, is it correct to say, that in these two invoking methods, this is always going to return the object the method is contained within (if that makes sense)?
In the first example, doSomething() is, in reality, defined within the window object - so is a property of the window object, even if we do not define it (or reference it).
Therefore, can it not be said that, in reality, invocation as a function is invocation as a method? Or not?
Imagine defining your function, not in the scope of the global object like you did, but in the scope of another function:
function outer() {
var inner = function(){console.log(this)};
inner();
};
outer();
What do you think the this will be bound to ? What will be printed ?
You might believe it will be the outer function object but its turns out that it will always be the global object.
It is just as if you had written:
function outer() {
var inner = function(){console.log(this)};
inner.call(window);
};
outer();
This is a quite hazardous and far from intuitive JS "feature".
So, to get back to your first example, what you are doing is basically this:
doSomething = function () {
console.log(this);
}
doSomething().call(window);
And, like Yoshi pointed out, if you were using the ES5's strict mode, you would end up doing something like that instead, which is, in my opinion, far less dangerous:
doSomething().call(undefined);
It also gives you a strong hint about the fact that you should never use this in a function ;)
I have a function which allows user to pass a function.
function withPredicate(func){
//...
}
Inside my function, I need to detect whether the func that user pass in has closure or not.
It is not enough to get the function name and search it in window scope. User might pass in an anonymous function without closure like:
var func = function(x){return x;};
withPredicate(func);
EDIT:
I think I need to implement a function which takes a function as a argument and return bool.
function hasClosure(func){
//...
}
so several test cases are:
hasClosure(function(x){return x;}); //return false
var something = 30;
var func1 = function(x){return x.age < something;}
hasClosure(func1); //return false
var Closure = function(){
var something = 18;
var itself = function(x){
return x.age < something;
};
return itself;
};
var func2 = new Closure();
hasClosure(func2); //return true
The last one return true because func2 is not top-level function. When I see some free variable inside the function body like something, it may resolve to the variable defined in its closure other than the one defined in window.
Actually, what I need to do now is to do some manipulations based on the func that has been passed to my function. I can use JSLint to get the undeclared variable. But I also need to resolve these variables. It is acceptable that I can only resolve variables in global scope. But I still need a way to make sure that resolving these variables in global scope is correct. So I need to detect closures.
Is it possible to do that programmatically in javascript?
Alright this is really hacky and probably not worth the effort in actually writing unless your linting or something :)
Basically what you're going to have to do to determine if a function is a closure is call func.toString() which will give you the source of the function. You can then parse the function using some sort of parser which determines all the variables of the function func. You also need to determine and track how these variables are defined. In your criteria in op the criteria for it being a closure is having a variable that is defined outside of function scope and outside of window scope (thus closure scope). So if you can find any variables defined outside of these two scopes we've found a closure.
So heres the pseudocode of hasClosure(), have fun implementing.
func hasClosure(func)
source = func.toString(); //eg "function x(a) {return new Array(a)}"
variables = parseJSForVariables(source)//finds a and Array
for variable in variables:
if(variable not in window)
if(variable not defined in function)
return true //we got a closure
return false //not a closure
The correct answer highly depends on what a "closure" means in this context. The function from the question does not use the variables from the outer scope so, roughly, closure is not created for this function. But strictly speaking, closure is created for any function and binds definition context with the function. So whatever you want to detect, it requires a detailed specification.
But I can assume that the closure here means whether the function references variables declared in outer scope (just like https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures specifies). One of the static for analysis libraries can be used for this. For example, JSLint reports used but undeclared variables. Assuming that undeclared variables are just from the upper scope, this indicates that closure is created.
I know I can define properties on functions, which can then be accessed from within the function. Right now, the only syntax I can work out involves two statements. Is there a more concise way to express the following:
function myFunc() {
// do some work
}
myFunc.myProp = 0;
I'm not looking for a solution that is fewer characters -- this isn't code golf. I'm asking something more along the lines of "are there different patterns of function declaration that have this other desirable merit?" This is almost about ways to use closures (because I suspect the answer lies there).
Thanks!
Especially if you want to access properties of the function from inside the function itself, you're better off doing this:
var theFunction = function() {
function theRealFunction() {
// the code
if (theRealFunction.something == "not whatever")
// do something
// more code
}
theRealFunction.something = "whatever";
return theRealFunction;
}();
What that does is wrap your function declaration up in an anonymous function. The problem with accessing function properties via the function name is that it must do that by finding the function's name in the surrounding scope. That's kind-of icky, but at least this way it involves a scope that's essentially private. It'll work whether or not the resulting function (returned as the return value of the anonymous function) is assigned to a different variable, passed to a function as a handler function, etc.
This really, really all depends. If you're looking for private variables, then you can easily return a function from the function -- an inner-function will contain access to its parent's scope.
var outer_function = (function () {
var private_var = "secret",
public_var = "public",
inner_function = function () {
return private_var;
};
inner_function.public_var = public_var;
return inner_function;
}());
outer_function now equals inner_function, with the benefit of having access to the enclosed data. Any properties attached to the inner (in the way you did) will now be accessible as public properties of outer.
To this end, you can return, say, a constructor for a class, with public-static properties, with the enclosed vars acting as private-static properties, shared between every instance of the "class" you build.
Not exactly the answer to your question, but if you ever want to read up some different design patterns that can be used when defining a javascript function, this is one of the best articles I've ever read on the topic:
http://www.klauskomenda.com/code/javascript-programming-patterns/
I'm fairly new to JavaScript and I'm cleaning up some JavaScript code I downloaded. One of the inconsistencies in this code is mixed usage of both this and the local variable that that references it.
An example code snippet (private method within a jQuery UI widget):
_populateLists: function(options) {
//do stuff with this
var that = this;
options.each(function(index) {
//use both this AND that, they are different in this scope
});
//here this and that are the same thing
//I want to be consistent, is one preferable over the other?
},
In many places throughout the code, where the scope is such that this === that, there is mixed usage, even within the same line of code.
For the sake of readability and maintainability, is it preferable to use this or that?
Note: I realize a lot of these types of things depend on developer preference. But before I decide to rewrite the code to use one over the other, I'd like to understand any reasoning if/why one would be preferred over the other.
EDIT: In this script, I think the only reason this is being assigned to a local variable is so that it can be referred to from within the inner closure.
The reason that the value of this is commonly assigned to a local variable is so that you can close over that value and use it inside a nested function.
this is a special variable and somewhat different from normal local variables in that it is automatically set to the object upon which a function was called (if any); otherwise, the global object. However, this intrinsic value of this is somewhat muddied by jQuery's liberal use of call and apply, which allow the caller to specify the value of this.
In a nested function, this does not inherit the value of its parent's this in the same way it would inherit a parent's local variables through the scope chain.
Because of this, we have to stash the value of this in a local variable if we need it inside a nested function, such as the each callback in your example.
var a = { fn: function() {
// here, `this` is the object `a`
var x = this;
function b() {
// here, `this` is `window` because `b` is invoked with no context
// ...but we still have access to `x`, whose value would be `a`
}
b();
}};
a.fn(); // by invoking `fn` as a property of `a`, we implicitly set `fn`'s
// `this` to `a`.
// Compare to:
var f = a.fn;
f(); // we now invoke `fn` with no context, so its `this` will be `window`.
a.fn.call(window); // or by specifying context explicitly
Of course, when you're still in the parent scope, this will still equal that (or self or whatever). At first glance, it may seem like there's no difference between the two, but there is one important performance impact:
Minification. If you assign this to a local variable, all references to that variable can be reduced to one character. References to this cannot. Compare this minified output:
function a() {this.w=1;this.x=2;this.y=3;this.z=4;}
function b() {var t=this;t.w=1;t.x=2;t.y=3;t.z=4;}
With 4 references to this, you save bytes by using a variable. If you have to capture this for an inner function anyway, using the local variable instead of this in the outer function gets you savings even with a single reference.
There isn't any reason, other than the standard subjective rationales of consistency and meaningful variable names.
If you go to the trouble of assigning this to a local variable, it's probably a good idea to use it, especially if you've given the local variable a useful name:
$('body').on('click', '.something', function() {
var clicked = this;
// now "clicked" is the element clicked on
});
for a jQuery example, but it's the same issue regardless of library or in raw JavaScript. Personally I think "that" is a pretty weak variable name in almost all cases.
If the purpose of assigning this to a local variable is to achieve semantics, then it would make sense to use a semantic variable name and then use the variable rather than this.
But since the purpose of assigning this to a local variable in this scenario is to cache it for use in an inner function, I think it's more readable/semantic to continue to use this in the outer scope.
While that is not normally a very good variable name, I think the meaning remains clear in this scenario. In my mind, in the inner scope, that is to this as parent is to self.
And since this is a jQuery UI widget, I looked at the source of some of the standard widgets that 'ship' with jQuery UI. It seems to be a standard convention to use this throughout except when needing to refer to the this of the outer scope. In the latter case, this is cached in a variable named that. Even when the local variable exists, it's only used in the inner scope.
Example for clarity:
_populateLists: function(options) {
var that = this; //we'll need `this` within a closure later
//do some stuff with `this`
options.each(function(index) {
//do stuff with `this` AND `that`
//`that` is the `this` of the outer scope
});
//do some more stuff with `this`
},
If consistency is the goal, then it makes sense to follow the same convention used by standard jQuery UI widgets.
When assigning a variable to $(this) when using jQuery, it is preferable to use $this as it refers to a jQuery object ( $ ). It is commonly used when $(this) no longer refers to the parent object when in the scope of another function.
The variable name however does not matter and simply refers to the object assigned. We could use $this, $that, $obj, that, obj, button etc. as our variable name, however this in javascript is a reserved word referring to the object in the current scope so we cannot use this as the variable name. You cannot assign any type of value to this or $(this).
Example...
this = 'something'; // or
$(this) = 'something';
Both of the above statements will throw an exception.
An example using $this = $(this); is shown below
To change the html of a button with the id of "someButton" after a successful jQuery post...
$('#someButton').click(function() {
var data = $('form').serializeArray();
// some validation or something
$this = $(this);
// note the lack of the var command to
// globalize $this within the click function
$.post('somePage',data,function(html) {
$this.html(html);
// identical to $('#someButton').html(html);
});
});
I have a 3rd party JavaScript application that declares several global functions and needs some variables to be defined for those functions to work. I would rather not define those variables in the global scope. Here's an example:
Suppose you have a globally defined function foo that prints out the value of an externally-defined variable named x.
function foo() {
console.log(x);
}
I think the only way for x to have a value within foo is if x is also a global. I hope I'm wrong. What I would really like to do is this:
(function () {
var x = 'someValue';
var bar = magicallyFixSoXIsntGlobal(foo);
bar();
}());
I guess I could do:
(function () {
var x = 'someValue';
var bar = Function(foo.toString());
bar();
}());
But that seems pretty much like eval. (If it comes down to that, I'd rather have global spam than use eval.)
Is there any way to "fix" the global functions so they can refer to the enclosed values?
Assign a value to a window's property, call the function, then use the delete operator to truly remove the variable.
window.foo = 'bar';
magic();
delete window.foo; // Because `foo` is defined without `var`, it can be deleted
The obvious solution is to modify foo to take x as a variable. But, assuming you can't / don't want to do that, I can think of two options:
declare x as a global variable.
Wrap foo's declaration in a closure.
The first will certainly make foo work, but please don't take Rob W's approach. Remember that the reason people tell you "don't clutter the global namespace" isn't because they're worried about unused variables hanging around (that can be a problem, but it's not specific to the global namespace). It's because having multiple functions using the same namespace increases the chances that one will overwrite the other's variables. Here's how you would use the global x without bludgeoning the rest of your code.
!function(x, exists) {
window.x=10;
foo();
if(exists)
window.x=x;
else
delete window.x;
}(window.x, 'x' in window);
The second option shouldn't be too hard if foo is currently just a function declaration within your code. In that case, change it to:
!function() {
var x=10;
function foo() {
[...]
}
// foo can only be called within this block
}();
Or if foo must be global, but you still don't want x to be global:
!function() {
var x=10;
window.foo=function() {
[...]
};
// now foo can be called anywhere, and will still use the x declared above
}();
But if foo is included via an external script then it gets more complicated, and I don't think you could use this method without modifying foo. (You could also use ajax and eval, or just eval, but I think you're right in avoiding that function.)
This is what function parameters are for
function foo(x) {
console.log(x)
}
You could hack it horrible if you wanted by converting the function to a string and creating a new function which accepts parameters, but that's dirty as hell