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
Related
On the Browser, it would look something like
//retreive all enumerable of `this`
function globalMems() {
var g = this;
var ret = {};
for (var prop in g) {
ret[prop] = g[prop];
}
return ret;
}
On Node.js, this is not the same as used on the browser to refer to the global object (window). How can I retrieve all members global to a certain module in Node.js? I don't think there is any direct access to a variable that refers to it. global is far beyond the specific module, this is not it when used to refer to it as in the browser, different behavior of keyword "this" between node.js and browsers, and modul is not it.
this will work for your function in Node.js.
globalMems.call(GLOBAL);
GLOBAL in Node.js at some extent substitutes window in browser.
However, my advise would be to read more about this in javascript in general. MDN article is a good start. And not use global scope in Node.js for your developerment needs
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.
I'm learning JavaScript and going through this tutorial on jQuery's website.
In following example
// A function being attached to an object at runtime
var myName = "the global object";
var sayHello = function ()
{
console.log("Hi! My name is " + this.myName);
};
var myObject = {
myName: "Rebecca"
};
var secondObject = {
myName: "Colin"
};
myObject.sayHello = sayHello;
secondObject.sayHello = sayHello;
sayHello(); // "Hi! My name is the global object"
myObject.sayHello(); // "Hi! My name is Rebecca"
secondObject.sayHello(); // "Hi! My name is Colin"
I don't see expected output when sayHello() is invoked. Instead variable is undefined. But if I define global variable by assigning it to window.myName it works.
I'm using Chrome Version 25.0.1364.152 m.
Is tutorial incorrect or am I missing something ?
Full HTML is here: http://pastebin.com/4M27vDB4
UPDATE: Accepted answer explains what happened. I also want to mention possible solution - declaring global variable above without var. Because of following:
Furthermore, variables that are declared inside a function without the
var keyword are not local to the function — JavaScript will traverse
the scope chain all the way up to the window scope to find where the
variable was previously defined. If the variable wasn't previously
defined, it will be defined in the global scope, which can have
unexpected consequences.
You have put this code inside
$(document).ready(function ()
// ...
});
closure. In this case context inside it will not be window (it will be document object) and you will get undefined as you describe.
in your program you have used this.myName. this keyword is used to point current object. when you call only sayHello() then in that case "this" means "window" because default current object is window. Now you have not defined window.myName then it will give "undefined".
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.
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.