This question already has answers here:
this in a global scope
(4 answers)
Closed 9 years ago.
I have read a couple of articles on the web explaining this in Javascript. While the articles
have helped a lot, the behavior shown below is still unclear to me.
Here it says:
In the global execution context (outside of any function), this
refers to the global object, whether in strict mode or not.
If so, can someone please explain the behavior (noted in the comments) when the following code is
run with node.
console.log(this); // Returns an empty object: {}.
// Why does this line not return the global object.
var somefunc = function(name) {
console.log(this);
}
somefunc(); // Returns the the global object. I think I understand this. The function is
// invoked in a global context.
somefunc.call(this); // Again returns the empty object. Why?
Thanks for your help.
EDIT (as requested by below by the moderators)
*How is this question and the chosen answer different from the one linked above*
I think both the question and certainly the answer here is clearer than the one that is considered a duplicate. The answer here clarifies what node is doing by giving example code, which is more helpful.
The first and the third showing of this should be identical in any case: in first case you just output the current value of this, and in the third you pass, again, the current value of this into somefunc (as a context argument).
But in the second, it's different: you call this function without assigning it any specific context, so this inside it points to a global object.
Why do you get an empty object as a result? One explanation is that your code is actually wrapped into some generic closure, like this:
var sandbox = {};
(function() {
console.log(this); // 1
var somefunc = function(name) {
console.log(this);
}
somefunc(); // 2
somefunc.call(this); // 3
}).call(sandbox);
As this function is called in sandbox context, both 1 and 3 point to sandbox - that is an empty object. 2 is different: you don't supply any context to this function call, that's why inside the function (when it's called that way) this points to global.
And that's exactly what happens when you try to access this in a global context of Node module. I'll quote an explanation from this discussion:
Node's modules are wrapped in a closure, which is evaluated in the
this-context of the exports object. So, if you do var a = 3, then
it won't be added to this, global, or exports. But, if you do this.a
= 3 then it'll be added to this and exports.
See: https://gist.github.com/788414
Note that it's quite different from using the code as it is within a browser. It's not wrapped in any closure, so all the calls - 1, 2 and 3 - are referring to the global object. And that's, as you know, window.
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
I am creating a program which will, ultimately, create thousands of small objects (ideally about 60,000 of them), each containing specific information. It will be loading each object from a small JSON file which has already been created and is sitting within a directory tree structure on the server.
How it finds the files is immaterial to this question (let's say it's outside the "scope" of it) however I'm trying to understand how this works by stepping through the program.
Assume that I have simplified this somewhat as well; as I know many of you may catch that I seem to be adding an unnecessary layer between my request to load the data and actually loading it (which obviously I could via jQuery's $.getJSON().done()), however since there's the file system structure to take into account, the program also needs to handle that part as well.
Data = function() {
var VERSION = 1.1;
if (this.constructor === Data) {
throw new Error("Objects may not be directly instantiated from an abstract class.");
}
}
// Loads a file with the path from the root set in config.json
Data.prototype.loadData = function(treePath,callback) {
// does data loading stuff here and proceeds through, eventually getting to this line:
callback(req,loadedData);
}
Now, I've got an abstraction layer in there - I don't want the Data object to be created in and of itself, which is why it throws and error should someone call "new Data();" That's intentional.
I will then have two objects which inherit Data; both with methods which deal with the loaded data in different ways. Since the file tree structure is the same for both, however, it makes sense to create an abstract object to inherit from. (OR, as a sub-question, is this a good argument for an object literal for the Data object?)
Now, I call the loadData from FOO and then Data will call the callack, which is inside FOO. I have tried declaring this as FOO.prototype.pareseData, and FOO.parseData, and it makes no difference.
FOO.parseData = function(req,path) {
// Parse the data and deal with it as needed.
}
Stepping through, when I call FOO from the main program and tell it to start loading the data, I can watch the "this" value. Initially, this = FOO, as expected; and this remains FOO until Data calls the callback function.
Once the code hits FOO.parseData, this changes from FOO to "window".
And I have no idea why...?
Thats because in javascript, "this" is a reference to the current scope, so, If you call a function/callback outside the original scope, most probably that "this" will be the "window", since "window" is the one that is calling the function/callback.
A workaround in order to maintain "this" to the scope you want to, you have to bind your functions to that given scope when you are declaring it:
function Foo() {
this.bar();
}.bind(this); //-> Here you bind Foo to the current scope, so inside Foo, this will be always the scope where it was bound.
I strongly recommend you to read this article.
http://ryanmorr.com/understanding-scope-and-context-in-javascript/
Your problem is explained in 3rd paragraph - What is “this” Context:
"Context is most often determined by how a function is invoked. When a function is called as a method of an object, this is set to the object the method is called on:
var obj = {
foo: function(){
alert(this === obj);
}
};
obj.foo(); // true
The same principle applies when invoking a function with the new operator to create an instance of an object. When invoked in this manner, the value of this within the scope of the function will be set to the newly created instance:
function foo(){
alert(this);
}
foo() // window
new foo() // foo
When called as an unbound function, this will default to the global context or window object in the browser. However, if the function is executed in strict mode, the context will default to undefined."
This question already has answers here:
What does "this" mean in jQuery? [duplicate]
(6 answers)
Closed 7 years ago.
Reviewing some legacy code and saw it. The function body was done in pure Javascript without using any 3rd party library.
Could anyone shed a light on the use of "this" in (function() { })(this)?
Full codes:
(function() {
var root = this;
var SOMEVAR;
SOMEVAR = root.SOMEVAR = {};
SOMEVAR.windowOffset = 0;
SOMEVAR.defaultBase = 195;
SOMEVAR.resizeIFrame = function(){
// some codes
};
SOMEVAR.resetIFrameSize = function(height) {
// some codes
}
window.SOMEVAR = SOMEVAR;
})(this);
I actually read all "this" related usages before I asked the question. I just couldn't find this usage fits in those I read. And somehow, I don't think the "this" here is not even necessary because all the codes want is to create the "SOMEVAR" and bind it to "window". Am I correct?
Thanks
This is a somewhat weird example of an Immediately-Invoked Function Expression (IIFE). The first part:
(function(){})
simply defines a function (the outer parentheses are unnecessary). This function is then called, passing this as an argument. Usually one would actually declare a parameter and then do something to the parameter inside the function:
(function(context) {
// do something to or with context
})(this);
What object is actually referenced by this depends on where this code is executing and whether strict mode is in effect. See the docs for this for more information.
You're defining an anonymous function and then immediately invoking it with the this parameter.
If you're just looking to understand the meaning of this, then refer to this other question.
Ah, what is this. The oldest question in the javascript book. Generally speaking, this refers to the context that the current code is being executed in. If you have "top level" code being run straight in a script tag, it refers to window. In a click event? The current element. In a constructor? The object that will be constructed. You can even make it whatever you want with call and apply.
If you see this construct:
(function(ns) { })(this);
not inside other function then this is a reference of default namespace of script execution. In browsers that default namespace has quite strange name window therefore the following will output true:
(function(ns) {
console.log( ns === window );
})(this);
Such ns (namespace) variable is useful when you need for example check variable existence in namespace. This, for example:
alert(foo);
will rise an error "undefined variable foo", but this:
(function(ns) {
alert(ns.foo);
})(this);
will show alert with the word "undefined".
Another usage is in modules that can work as inside browser as in node.js and the like. Node.js has no notion of window so that construct above is the only reliable way to get reference to default namespace/scope object.
This question already has answers here:
Is 'window' always on top of the scope chain in javascript?
(5 answers)
Closed 8 years ago.
As I understand from my practice (in the Google Chrome Console), we can change the definition of predefined functions. Let me explain through code:
function alert(){
return 2+2;
}
and I am calling alert("hi"), it is returning 4, it's Ok, as we have defined.
But, even when I call window.alert("hi"), it is returning 4, which is unexpected (for me).
Here I just created a new function, I have not mentioned any object name or Prototype property, but still it is overriding the window object properties itself.
My doubt is, if we change the definition of the function, will it override the definitions of a function with the same name in all the objects??
Let's say I have two objects objA and objB, both are having a function named strange(). Now I am defining a function strange() in the outside of both the objects. Then, whether it will override the definition of strange() in both objA nad objB? If so, why?
If so, how to prevent this? means how to prevent the overriding in all the objects?
Thanks in advance...!!!!
No - by declaring function alert() you are redefining window.alert() function because the default scope is window
var newObj = {
alert: function() {
return "this is a functino on my newObj object";
}
};
function alert() {
return 2 + 2;
}
console.log(alert());
console.log(window.alert());
console.log(newObj.alert());
The reason defining alert overrides the window property is because you declared it in the global context; anything declared in the global context will, by default, attach itself to window. To not override the window object, declare your function inside another function (or use a different name):
// This creates an anonymous function
(function() {
// Since alert is defined in this function (not the global scope)
// It won't override window.alert
function alert() { /* Do something */ }
})();
// You can no longer access the old alert here, so alert will refer to window.alert
In addition, if you add alert to a specific object, it will not change the alert of any other object, unless you use a with statement (considered bad practice).
var myNamespace = {
alert: function() { /* Custom alert */ }
}
// Will not change myNamespace.alert
function alert() {}
No I don't think so - with the alert function, the "window." prefix is assumed so really window.alert() and alert() are the same thing. I guess it's a short-cut to stop you havign to type window. all the time.
Regarding your other example, objA.strange() isn't related to objB.strange() (assuming objA and objB are in fact different objects).
the function strange() outside of both these objects is actually in window.strange() (it's implied) so again it's a different function under a different object.
You can, I gather, use prototype to redefine native JS functions, but this is normally undesirable.
If you define a variable or function in the default scope in javascript (creating a function directly inside a <script> tag for instance), it is considered part of the window object (if javascript is executed in a browser environment).
So, when you call (the default) alert, you arev actually calling window.alert.
Let's say I have two objects objA and objB, both are having a function
named strange(). Now I am defining a function strange() in the outside
of both the objects. Then, whether it will override the definition of
strange() in both objA nad objB
A definition of strange outside both the object scope (closure) will not impact the definition of the function (method) in the object. But if you define strange within the object again, the latter one will shadow the previous one.
It boils down to the scope of the function and the closure withing which the function (or variable) is defined.
See also
Functions and function scope from MDN. This will answer most of your questions
Closure from John Resig's Learning Advanced Javascript
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 9 years ago.
Code gives me:
A
B
C
When I click on A B C it always shows me the last one "vodka".
I want "martin" (for A), "lindsay"(for B), "vodka" (for C)
Please help me on my example.
myArray = [
{
letter: "A",
brand: "martin"
},
{
letter: "B",
brand: "lindsay"
},
{
letter: "C",
brand: "vodka"
}
];
var list = '';
for (var i = 0; i < myArray.length; i++) {
list += "<br>" + myArray[i].letter;
new_info = myArray[i].link;
(function(new_info) {
$(this).click(function(){ //this - refers to A or B or C
$('#box2').text(new_info);
});
}).call(this, myArray[i])
}
$('#box1').append(list);
Edit:
I said I wasn't going to write your code for you... well, I did: this fiddle does exactly what you're looking for. I solved the issue with context (this), closure issues and implied globals. It still needs a lot of work, but the fiddle shows what everybody has been saying: $(this) does not, cannot and will never point to a string constant like "A", or "B".
Sorry to say this, but your code is full of problems, but I will address the specific issue you're asking about here.
Inside the loop, you're assigning a click handler that, basically looks like this:
function()
{
$('#box2').text(new_info);
}
Where new_info is a variable that is declared in a higher scope. So far, so good. The problem is, the function object you're creating doesn't have its own copy of whatever value that variable (new_info) happened to hold when that function was created. Instead, the function references that variable. So when any of those functions is invoked it $('#box2').text(new_info) will be resolved to $('#box2').text("whatever value new_info holds when function is called"), not $('#box2').text("whatever value new_info was holding when function was created"). You can give each callback access to a copy by simply adding a second function to your code:
$(this).click((function(currentNewInfo)
{
return function()
{
$('#box2').text(currentNewInfo);
}
}(new_info)));
What I'm doing here is creating a function, that takes an argument, and calling it immediately. I pass new_info as an argument, so the value of currentNewInfo will be what new_info holds at that time (aka a copy)
The function I called (IIFE - or Immediately Invoked Function Expression) returns the actual callback. In this callback, I don't reference new_info, but the argument of the IIFE: currentNewInfo.
Because each function has its own scope, that variable is enclosed (hence the name closure), and cannot be accessed or altered from outside. The only thing that can still access the currentNewInfo variable is the function the IIFE returned.
Perhaps you are worried about name-conflicts (each callback you create uses references currentNewInfo), but that's not the case: each callback was created by a separate function, and therefore has access to a different scope. It's not possible to have a name conflict between scopes that don't access each other... Just to make things really simple to understand:
Where /\ and /\
|| ||
is return function() is scope of IIFE
So closures have access to a function's scope after it returns. That scope has precedence when it comes to resolving an expression to a value. To understand this better, here's a similar diagram to show you how JS resolves expressions:
Where each pink "outer environment record" is a scope of a function (closure scope of a function that has returned already or function currently being called). The last environment will either be the global object, or null (in strict mode). That's all there is to it.
Honestly, closures are tricky to get your head round at first, but once you grasp what I tried to explain here, they're great fun.
Check this link I can go on to explain the use cases and benefits and ways nested closures work, but I'd end up writing a book. The link I posted does a great job at explaining how closures work using rather silly drawings. It may seem childish, but they actually helped me a lot when I was trying to grasp the concept of lambda functions, closures and scopes out-living a function-call. The diagrams above are taken from the page I linked to, which explains the concepts a bit more in-depth, but I still think the simple, crude drawings are pretty self explanatory.
Other issues:
As someone pointed out: "What are you expecting this to reference". Looking at the snippet, this will just reference the global object (window), attaching the same/similar event handler to window simply doesn't make sense if you ask me.
Global variables are evil, implied globals even more so. I can't see new_info, nor myArray being declared anywhere. The way JS resolves expressions is a tad unfortunate and falls back to creating global variables, without so much as a peep:
var bar = 666;//global, always evil
function createGlobal()
{
var local = 2;
foo = bar * local;
}
createGlobal();
Let's look at foo:
JS is in createGlobal scope: var local is declared, and assigned 2.
foo is used, and assigned bar*local
|| || \\=>found in current scope, resolves to 2
|| ||
|| \\=>found in global scope, resolves to 666
||
||
||=> JS looks for foo declaration in function scope first, not found
||
||=> moves up 1 scope (either higher function, or global scope)
||
\\=>Global scope, foo not found, create foo globally! - hence, implied global
\\
\\=>foo can now be resolved to global variable, value undefined
Excessive DOM queries: your event-handler callbacks all look like so:
$('#box2').text(new_info);
This ($('#box2')) is actually the same as writing document.getElementById('#box2'). Which is practically English. Think about it like this: each time the client clicks on $(this) - whatever that may be, you're accessing the DOM, and scanning it for an element with a given ID. Why not do this once and use a reference kept in memory to change the text. That saves countless DOM queries.You could use a variable, or (in light of what I explained about closures), a closure:
var list = (function(box2, list, i)
{//list & i are arguments, so local to scope, too
for (i = 0; i < myArray.length; i++)
{
list += "<br>" + myArray[i].letter;//<-- don't know why you use this
//new_info = myArray[i].link; no need for this var
$(this).click((function(new_info)
{//new_info is closure var now
return function ()
{//box2 references DOM element, is kept in memory to reduce DOM querying
box2.text(link);
};
}(myArray[i].link));//instead of new_info, just pass value here
}
return list;//return string, assign to outer variable
}($('#box2'), ''));//query dom here, pass reference as argument
I've been doing some javascript reading, and I've gathered that a closure has access only to the closure "wrapping" it, or, you might say it's immediate parent. Now I've been playing a bit, and I see in this jsfiddle that even deep nested functions have access to to vars defined way up.
Can anyone please explain that? Or explain what have I got completely wrong?
http://jsfiddle.net/tPQ4s/
function runNums() {
this.topVar = 'blah';
return function(){
(function() {
(function() {
console.log(topVar);
})();
})();
}
}
var someFunc = runNums();
someFunc();
Without going too deep into the details, a closure technically describes a array like variable within the such called Activation Object that is handled from the javascript engine. An ActivationObject contains Variables declared by var, function declarations and formal parameters.
That means, anytime a new function (-context) is invoked, internally a new Activation Object is created. That object is part of the new Execution Context, a typicall EC looks like:
this context variable
Activation Object
[[Scope]]
The interesting part here is [[Scope]]. That variable contains all Activation Objects of all parent context and is filled when the EC is called. So now, when a function wants to access a variable, the name resolution process first looks into its own Activation Object, if nothing is found the search continues in the "Scope chain", which is just an Indexed search through our [[Scope]] variable (which again, is an array of parent contexts). Thats why we also speak a lot about "lexical scope" in ECMA-/Javascript.
Note: The above behavior is not described entirely, that would need several pages of text. Also it describes the ECMAscript3 262 specification. Things work a little different in ES5, but its still around the same thing
That is because the chain runs further up to the top context.
In the example, that would be:
window < runNums < anonymous < anonymous < anonymous
Variables living in any of these will be available in the last anonymous function. In runNums, only variables living in runNums or window will be available. In the first anonymous function, only its variables and those living in runNums or window will be available, etc.
this is nothing but the Window object here.
Here runNums is a global function and runNums() is equal to window.runNums(). So this is window and this.topVar is window.topVar. Obviously it will be accessible from anywhere.
Try this and see the difference
var someFunc = new runNums();
someFunc();
The deep nested functions have not been executed. You did not return them for executing.