This code results in "!" being logged on the console.
var g = {};
(function() {
var t = this;
t.x = "x";
g.a = function() {
console.log(t.x);
};
})();
(function() {
var t = this;
t.x = "!";
g.b = function() {
console.log(t.x);
};
})();
g.a();
Do anonymous functions share a this? Am I using this wrong? I don't really understand what's going on here.
I'd like for g.a() to continue returning the value of x defined in the first anonymous function.
I'm using node.js if it makes a difference.
In the immediate functions, this refers to the global object [docs]. So in this case in both functions this indeed refers to the same element and you are overwriting x with the second call.
What object this refers to is determined by how the function is called.
If you just execute a function with funcName();, then this refers to the global object.
If the function is assigned to a property of an object, obj.funcName() , this refers to the object.
If you call the function with the new operator, new funcName();, this refers to an empty object that inherits from the functions prototype.
You can also explicitly set this by using call [docs] or apply [docs].
Instead referring to this, you could create a new object in both functions:
var t = {};
Additional note: It makes no difference whether you run the code in the browser or with node.js. The global object is part of the specification and has to be provided by the execution environment. In browsers it is the window object, I don't what it is in node.js, but it does not matter as long as it follows the specification.
Felix Kling is the right long answer. But I wanted to chime in with what I think you actually want:
var g = {};
(function() {
var x = "x";
g.a = function() {
console.log(x);
};
})();
(function() {
var x = "!";
g.b = function() {
console.log(x);
};
})();
g.a(); // "x"
g.b(); // "!"
Now g.a() and g.b() both print out x, but each function has their own separate x shared with the closure. If these vars should be private an only accessible internally to each of these functions, this is how you hide them and persist them through multiple calls.
When I look at this script in the debugger in Chrome as you've shown it, the "this" value in both anonymous functions is set to the global variable "window". That means that each anonymous function is setting the value of window.x so the last one executed wins and is the value that survives, thus window.x == "!" after the second anonymous function executes.
It's unclear to me what you expected "this" to be or what you're actually trying to accomplish with this code so I don't know what alternative to suggest. If you just want the previous state in the anonymous function to survive for the internal function, then you can just rely on local variables (which will survive in the closure) and not use the "this" reference at all. Squeegy's example shows that.
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'm fairly new to Javascript and wrote the following jQuery code which works:
function updateItems() {
var now = Math.round((new Date()).getTime() / 1000);
$(".something").each(function() {
$(this).html(now.toString());
});
}
updateItems();
Why does this work? One might think that now would not be accessible from inside the function. I guess I could run some tests to see what happens if I try to modify now from inside the function, if I run another each() right after that, etc. But a basic understanding of how the scope works here and generally in Javascript cases like this would be greatly appreciated.
Also, is this type of function accurately called a "dynamic function" or is there a better name for it?
When you use function() { ... }, you create what is technically called a closure. They effectively can capture everything from the enclosing scope.
If you use now in the closure, you would get the value of now when you execute the closure, and (potentially) not the value it had when you created it.
Note that the enclosing scope here is the scope of the outer function, not of the outer block, and you may have to take extra care if you're creating closures in a loop, for instance.
This is just a nested function. It has access to the now variable because functions have access to the variables in scope where they're defined (this is actually how globals work as well). It's called a "closure" (it "closes over" the variables in scope where its defined), which sounds obscure, but don't worry — closures are not complicated (disclosure: my blog) once you know a couple of things about how JavaScript works.
The fun thing here is that it closes over the now variable that's specific to that particular call to updateItems, and the reference it has is live (it's not a copy of now as of when the function was created). Each call to updateItems creates a new anonymous function you're passing to each, and each of those functions has access to the now variable created during the call to updateItems. In your case, you're just using it immediately and returning, but what if you kept a reference to the function? What then? The answer is that's fine, it keeps a reference to the now variable it relates to:
function say(msg) {
var f = function() {
alert(msg);
};
return f; // We return a reference to the function
}
var s1 = say("Hi");
var s2 = say("there");
s1(); // Alerts "Hi" (see below)
s2(); // Alerts "there"
The call to s1 alerts "Hi" because the function created by our call to say still has access to the msg argument we gave to say, even though say has returned. And the same for s2, of course.
And just to prove that it's not a copy as of when the function is created:
function say(msg) {
// Create the function
var f = function() {
alert(msg);
};
// Update `msg`
msg += " (updated)";
// Return the function
return f;
}
var s1 = say("Hi");
var s2 = say("there");
s1(); // Alerts "Hi (updated)"
s2(); // Alerts "there (updated)"
See how the function used the updated version of msg, even though the function was created before we updated it. The function has access to the variable itself, not a copy of the variable's value.
Can someone explain in detail what this snippet of js does?
(function (window) {
var test = window['test'] = {};
test.utils = new(function(){ ... })();
})(window);
I understand that the function is not globally scoped. I understand that it is creating a variable called test that points to a property in the window object that is an empty object. I also understand that utils is a property of test.
I don't understand what the purpose of the last part is (window); or why the utils function is being designated as new.
Please explain.
It creates a function and calls it immediately, passing in window. The function receives an argument called window and then creates an empty object on it which is available both as a property on window called test and as a local variable called test. Then it creates an object by calling a function via new and assigns that object to test.utils.
I don't understand what the purpose of the last part is (window);...
It doesn't really serve any purpose in the code you've quoted, because the symbol passed into the main (outer) function, window, is the same as the name of the argument receiving it. If their names were different, then it would serve a purpose, e.g.:
(function(wnd) {
})(window);
That would make window available within the function as wnd.
or why the utils function is being designated as new.
utils won't be a function (at least, not unless the code you've replaced with ... is doing something really strange), it will be an object created by calling that function.
The whole thing could be rewritten more clearly:
(function(window) {
var test;
test = {};
window['test'] = test;
test.utils = new NiftyThing();
function NiftyThing() {
}
})(window);
That still does the window thing for no reason, but hopefully it makes it clear what the new(function() { ... })(); bit was doing.
First of all, this is a self-invoked function.
It's invoked itself giving the window object as function input argument in order to ensure that, inside the whole function, window will have the expected meaning.
test.utils = new(function(){ ... })(); <--- This is an object constructor.
When the function is called using the new operator, it turns into an object constructor.
For example:
var conztructor = function() {
this.name = "Matias";
};
var obj = new conztructor();
alert(obj.name); // <--- This will alert "Matias"!
The purpose of (window); is creating a new variable and reference holding the JavaScript Window object instance, avoiding that other libraries may reuse the window (or any other) identifier and your own library may break because of this situation.
This is nice in order to avoid altering global scope identifiers that may be used by other libraries.
UPDATE
In response to some comments, run this code:
http://jsfiddle.net/wChh6/5/
What is happening here is that a new anonymous function is being declared. The last part with (window) makes a call to that function, passing window as a parameter.
Inside, the call to test.utils = new(function(){ ... })(); creates a new object (with contents defined by the function passed to new) and assigns it to test.utils.
When you define a function with last parentetheses, the function is executed itself after loading with the parameter given, in your case window
(function (window) {
var test = window['test'] = {};
test.utils = new(function(){ ... })();
})(window);
JS function definition : meaning of the last parentheses
In the following construct:
(function(){
var x = function(){
alert('hi!');
}
var y = function(){
alert("hi again!");
}
this.show = function(){
alert("This is show function!");
}
})();
Why does this refer to window object? Should everything inside IIFE be isolated from global scope? Are x and y functions also properties of window global object?
Also, even if I use put var h = ... at the beginning:
var h = (function(){
var x = function(){
alert('hi!');
}
var y = function(){
alert("hi again!");
}
this.show = function(){
alert("This is show function!");
}
})();
this still refers to window object -- I can just call show() from the global scope! How come?
The global context (window in a browser) is the value this gets when there's no other value to use.
Your local variables are local (that is, not properties of window). They're declared inside the function with var.
The reason why adding var h = (function(){... makes no difference is because of the way you call the function. The function reference is not a property value of an object (like something.func()), and you don't invoke it with .call() or .apply(), so therefore this refers to the global (window) object. That's just the way the language is defined to act.
#Pointy is correct, but he doesn't present the whole issue - you might be interested in this related answer. The issue here is that if you aren't using the new keyword, you aren't instantiating an object, so there's no instance for this to refer to. In the absence of an instance, this refers to the window object.
In general, you don't need this within an IIFE, because you have direct access to any function or variable defined in the anonymous function's scope - show() can call x() and y() directly, so there's no need for a this reference. There may be a valid use case for instantiating an IIFE with new, but I've never come across it.