What does "this" mean in this revealing module pattern - javascript

var abc=(function(){
var self=this;
return {
self:self
}
})();
When doing abc.self I get undefined what does this happen to be in this context.

What you have can be simplified for the purpose of the explanation in
(function(){ console.log(this) })();
Your expression (in the first set of parenthesis) defines a function. You then call this function without context (the this). This construct is called an IIFE. As you don't pass a context, the behavior depends whether it is called in strict mode or not :
In non strict mode, you would have the global object (window in a browser, global in node).
In strict mode, a missing context of a function call isn't replaced, it's undefined.
As you get undefined, I guess you're in strict mode. You probably have "use strict"; at the start of the file or in an enclosing function.
If you wanted to pass a context, you might for example have done
(function(){ console.log(this) }).call(someobject);

in that "root scope" this is window
and
console.log(abc.self);
results for me in
Window {top: Window, window: Window, ...}

this refers to the current object. In your condition this will be window, and as you're trying to get the value abc.self, you need to use like this:
this.self = this;
Now, only you can get the value:
var xyz = new abc();
xyz.self
But to note, you cannot use abc as the constructor like above code because you are using the closure.

Related

this.globalvar vs window.globalvar

I recently read somewhere (I am really sorry I can't provide the source) that you can use this.varname to access globals in replacement to window.varname to save 2 chars
var myVar = "global";
function myFunc() {
var myVar = "notGlobal";
alert( this.myVar ); //global
}
It seems to work, but I want to know if:
it is safe to use in old browsers
it is cross-browser compatible
it will fail under some weird circumstances
I don't think I'd do it, but it's completely cross-browser compatible if this is referring to the global object (window). Whether it is will depend on how the function in question was called (at global scope, this does indeed refer to the global object), and whether the code in question is in "strict mode" or not. (In strict mode, this does not refer to the global object. Kudos and upvotes to Esailija for pointing that out.)
In non-strict code:
So at global scope:
console.log(this === window); // true if not in strict mode
And similarly, if you have a function you call directly:
function foo() {
console.log(this === window);
}
foo(); // Logs "true"
But, in JavaScript, this is set entirely by how a function is called. So we could call foo setting this to something else:
var obj = {};
foo.call(obj); // Now it logs "false", `this` === `obj` during the call
Similarly:
var obj = {};
obj.f = foo;
obj.f(); // Also logs "false", `this` === `obj` during the call
So in conclusion, at global scope (not in any function call), yes, this is reliably pointing to the global object, and if you control how the function gets called and you call it without setting this to anything else (via call or apply, or by using it from an object property a'la obj.f above), then, again, it will reliably refer to the global object. This is covered by sections 10.4.1 (Entering Global Code) and 10.4.3 (Entering Function Code) of the specification. This is how it's been from the very beginning, I believe; certainly for the last 15 years, so you're unlikely to find a non-compliant environment.
More reading:
Mythical methods
You must remember this
It will not work in modern browsers if someone slaps "use strict" above your code as this will be undefined inside the function.
<script type="text/javascript">
"use strict";
...
function test(){
console.log(this);
}
test(); // undefined
</script>
Note that you can save much more characters just by assigning window to some variable at the top of your code and using that as it will be shortened to some one character variable by a minimizer.
(function(global){
global.foo();
global.bar();
})(window);
would be minimized to (without whitespace):
(function(a){
a.foo();
a.bar();
})(window);
Where as this would not be touched as it's a keyword.
this always has a value. And if this hasnt been overridden somehow, then it will be window where all your globals are.
It will work in all JS implementations, but beware! This is more brittle, and it won't always point to a global variable.
For instance:
var myVar = "global";
var obj = {
myVar: "property",
fn: function() { return this.myVar; }
}
console.log(obj.fn()); // "property"
This fails because in this context this is that object. But when executing a function that is NOT a property of an object, this will default to window, like your example.

node.js: Confusing usage of 'this' in the global scope

I've been toying with node.js lately and I ran into a weird behavior about the usage of this in the global scope of a module.
this is bound to module.exports in the global scope:
console.log(this === exports); // -> true
But this is bound to global in a method scope:
(function() { console.log(this === global); })(); // -> true
This also lead to this confusing behavior:
this.Foo = "Weird";
console.log(Foo); // -> throws undefined
(function() { this.Bar = "Weird"; })();
console.log(Bar); // -> "Weird"
I guess that the solution is to never use this in the global scope and explicitly use extends or global instead, but is there a logic behind all this or is it a bug or limitation in node.js?
The "logic" behind that is, that the value of this always depends on how a function is invoked.
In your case, you have a self-executing anonymous function, there, this always references the global object (non strict mode) or undefined (ES5 strict).
If you want to access the "outer" this value, you could either store a reference before executing that function, like
var outerScope = this;
(function() { outerScope.Bar = "Weird"; })();
console.log(Foo); // -> throws undefined
or re- .bind() the functions scope yourself, like
(function() { this.Bar = "Weird"; }).bind(this)();
In working on a simple CommonJS modules implementation, I had to think about what to do with this in the global scope of the module; it's not addressed by the spec.
I also set it up as the exports object at first, because I thought that would be useful, but later found some code I needed to "modulize" that was using this to get a handle to the global object, so I changed this back to the global object to provide as close of an environment to "normal" as possible for module code.
We can only guess at why node is set up the way it is (or ask the author), but my guess is it was done simply because it seemed like a useful idea, similar to the way you can give the module object an exports property in node and have it reflected in the module's actual exports (this behavior also isn't part of the spec, but doesn't go against it either).
As for the part of your question about this referencing global in functions, as the other answers explain, that's just the way this works; it's not a node-specific behavior, it's a weird javascript behavior.
I don't know if this is the exact intention of Node.js team, but I would be surprised if it was not. Consider this example ran in the dev console of a browser (e.g. chrome):
var x = function(){console.log(this)}
a = {}
a.x = x
a.xx = function(){x()}
a.x()
>> Object
a.xx()
>> DOMWindow
x()
>> DOMWindow
As you can see executing a method without specifying its context sets the context to be the global one. In this case the DOMWindow object.
When you are inside a module your context is the module, but executing a method in it without specifying a context with .call or .apply or obj. will use the global context, global, instead of the local one, module.exports.

what's the difference between Browsers and Node?

what's the difference between Browsers and Node? for instance:
setName.js on Node:
var setName;
setName = function (name) {
return this.name = name;
};
setName("LuLu");
//LuLu
console.log(name);
//undefined
console.log(this.name);
setName.html in browser:
<script>
var setName;
setName = function (name) {
return this.name = name;
};
setName("LuLu");
//LuLu
console.log(name);
//LuLu
console.log(this.name);
</script>
the the second log is different,why?
Node is a JavaScript engine, not a browser. The specific reason that you see undefined in Node, and Lulu in a browser? Differences in the global namespace:
In browsers, the top-level scope is the global scope. That means that in browsers if you're in the global scope var something will define a global variable. In Node this is different. The top-level scope is not the global scope; var something inside a Node module will be local to that module.
In the browser, this is a reference to the window object — the browser's global namespace — for all functions which are invoked unattached to an object (e.g. not like foo.bar()). In Node, this is simply not a reference to the global namespace.
N.B. console.log(this.name) in a Node interpreter will print Lulu, not undefined. That's because, in the REPL only,
> this === global
true
Further reading # How To Node: What is "this?"
Okay, one more edit as prompted by #Šime Vidas' comment regarding this in ES5 strict mode:
In the global context (outside of any function), this refers to the global object, whether in strict mode or not.
When the this keyword occurs inside a function, its value depends on how the function is called.
When a function is called as a method of an object, its this is set to the object the method is called on.
More interesting reading courtesy of Juriy Zaytsev (aka #kangax) in one of his blog posts.
Your browser code has the window host object. Node does not have that host object. When you set this.name, you are actually setting it to the window object aka making a global variable.
window.name === this.name // true

javascript "use strict" and Nick's find global function

So I saw a function that was, quite frankly beautiful in its simplicity as it allowed you to find the global object ( which depending on environ at the time may NOT have been window ) while within an anonymous function; however when you throw javascripts' "use strict"; mode it crumbles, due to the evaluation of the keyword 'this' changing. There were a few ways to accomplish this?
(function () {
var win = function () {
return (function () {
return this;
}());
};
//win now points to the global object no matter where it is called.
}());
Now, if these are called within the context of "use strict" we lose the functionality described, is there any equivalent that can be done in ES5 strict mode?
For reference
(function () {
"use strict"
//code here is in strict mode
}())
Access to the Global Object (before ES5)
If you need to access the global object without hard-coding the identifier window, you can do the following from any level of nested function scope:
var global = (function () {
return this;
}());
This way you can always get the global object, because inside functions that were invoked
as functions (that is, not as constrictors with new) this should always point to
the global object.
This is actually no longer the case in ECMAScript 5 in strict mode,
so you have to adopt a different pattern when your code is in strict mode.
For example,
if you’re developing a library, you can wrap your library code in an immediate function
(discussed in Chapter 4) and then from the global scope, pass a reference to this as a
parameter to your immediate function.
Access to the Global Object (after ES5)
Commonly, the global object is passed as an argument to the immediate function so
that it’s accessible inside of the function without having to use window: this way makes
the code more interoperable in environments outside the browser:
(function (global) {
// access the global object via `global`
}(this));
“JavaScript Patterns, by Stoyan Stefanov
(O’Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750.”
Solution:
var global = Function('return this')();
Works in all Browsers, Engines, ES3, ES5, strict, nested scope, etc.
A slight variation will pass JSLINT:
var FN = Function, global = FN('return this')();
Discussion
See How to get the global object in JavaScript?
Here's a snippet from Perfection Kills, using global eval.
var root = (function () {
return this || (0 || eval)('this');
}());
ECMA3, ECMA5, Strict mode, etc compatible, passes JSLint.

Reason behind this self invoking anonymous function variant

While looking at code on github, I found the following:
(function() {
}).call(this);
This is clearly a self invoking anonymous function. But why is it written this way? I'm used to seeing the canonical variant (function() {})().
Is there any particular advantage to using .call(this) for a self invoking anonymous function?
Edit: It looks like some commonjs environments set this to a non-global value at the top level of a module. Which ones, and what do they set this to that you might want to preserve?
By default, invoking a function like (function(){/*...*/})() will set the value of this in the function to window (in a browser) irrespective of whatever the value of this may be in the enclosing context where the function was created.
Using call allows you to manually set the value of this to whatever you want. In this case, it is setting it to whatever the value of this is in the enclosing context.
Take this example:
var obj = {
foo:'bar'
};
(function() {
alert( this.foo ); // "bar"
}).call( obj );
http://jsfiddle.net/LWFAp/
You can see that we were able to manually set the value of this to the object referenced by the obj variable.
.call(this) (was actually just () until I changed it) ensures your top level this to be consistent through strict mode, --bare option and/or the running environment (where top level this doesn't point to global object).
By using:
> (function() {
> ...
> }).call(this);`
then this in the scope of the code (probaby the global object) is set as the function's this object. As far as I can tell, it's equivalent to:
(function(global) {
// global references the object passed in as *this*
// probably the global object
})(this);
In a browser, usually window is (or behaves as if it is) an alias for the global object.
C={
descript: "I'm C!<br>",
F: function() {
//set this to the caller context's 'this'
(function() {
document.write(this.descript);
}).call(this);
//set this to 'window' or 'undefined' depend the mode
(function() {
document.write(this.descript);
})();
//member function's 'this' is the object self
document.write(this.descript);
}
}
window.descript="I'm window!<br>";
C.F();
(function() {}).call(this); could set the this in the anonymous to the caller context this, in above is C.(function() {})(); will set this to window or undefined depend the mode.
Self-invoking function are useful to execute its content immediately when the script is loaded. This is convenient to initialize global scope elements.

Categories