Does the value of "this" refer to the global object or the object "o" in the program below?
More importantly, what code could I run to test what the reference of "this" is?
function F() {
function C() {
return this;
}
return C();
}
var o = new F();
It refers to the global object (window).
Edit: Actually, it will refer to both, the global object and o, because they are the same. o will have a reference to the object returned from F() which is the object returned from C() which is the window object ;)
You can call console.log(this) to find out which object it refers to. It should give you a listing of all the methods of the object on the console and you should be able to infer from this which object it is.
For this to work in Firefox, you need Firebug. Don't know for IE.
Update:
#Anurag already showed you how to explicitly set this. If you just want to refer to this of a higher scope, you have to assign it to a variable explicitly. Example:
function F() {
var that = this;
function C() {
console.log(that);
}
C();
}
this refers to the global object in your program. To get this to reference the instance of F, try,
function F() {
function C() {
return this;
}
return C.call(this); // call C with the object of F as a context
}
var o = new F();
On Chrome, you could simply enter the variable to inspect, and its value will get logged. It's similar to doing a console.log(object), but much easier to work with. Here's a screenshot of running this code sample in Chrome. The value of the last statement o is automatically printed, and I printed it once again, just to be sure. It logged DOMWindow which refers to the global window object on the browser.
To add to the other answers:
When a function is called, this is set depending on how it's called. If it's called with myfunc.call or myfunc.apply, then this is set to the first passed argument. If it's called in the 'dotted' form, i.e. myObject.myfunc() then this is set to whatever is before the dot.
There is an exception to this rule, which is that it's possible to bake the value of this in with bind, in which case it will be whatever has been bound. i.e. in var boundfunc = myfunc.bind(myobj); then any time boundfunc is called, it would be like calling myfunc but with this referring to myobj regardless of anything else. Here's an example that does that:
function F() {
var C = function() {
return this;
}.bind(this);
return C();
}
var o = new F();
If none of these cases are applicable, then this is always either the global object (window if you're in a browser), or, if you're in strict mode it's undefined.
Related
When I run this code in node, the function foo prints undefined. But if I run the same code in the Chrome or Firefox console I get the right output (oops, global). Can anyone clarify why?
function foo() {
console.log(this.a);
}
function doFoo(fn) {
// `fn` is just another reference to `foo`
fn(); // <-- call-site!
}
var obj = {
a: 2,
foo: foo
};
var a = "oops, global"; // `a` also property on global object
doFoo(obj.foo); // "oops, global"
In browsers, global variables become properties of the window object. And when a function is called without a context, the context also defaults to the window object. Since you're calling foo() without supplying a context, this.a is treated as window.a, which is the global variable.
Node.js has a global object called global, but global variables are not made properties of that object. See Does node.js have equivalent to window object in browser. this.a is treated as global.a, but this is undefined because the variable declaration doesn't assign to it.
I'm trying to use variables placed inside a function. I'm not looking to do anything particular with this piece of code, but I want to figure out why bind / apply / call work for objects, and not functions.
function another () {
this.var = 'another test'
}
function test (){
this.var = 'test123'
console.log('this.first: ',this.var);
}
var bind = test.bind(another);
console.log('bind: ', bind());
.bind() works just fine for functions. It just doesn't do what you think it does.
See, functions are objects too. And treating them like objects doesn't mean they get called.
function a() { console.log("a was called"); }
function b() { console.log(this); }
var bound = b.bind(a);
bound(); // logs "function a() { }" in my console
In your case, once you've bound test to another, you have a new function that works just like test, but where this means another, and thus this.var means another.var. And all of this happens without another ever getting called.
I'm not sure entirely how you expect your code to work, cause it doesn't make much sense as it stands. But if you were to examine things after you run it, you would find that another.var now has the value 'test123'.
Even if you said another() beforehand, it wouldn't matter. Firstly because another isn't bound to anything, so to it, this means the global object. In a browser, another() would basically just be setting window.var. But secondly, test sets its own value -- so even if both functions had the same idea of what this.var means, test would overwrite it with 'test123'.
This will log "another test", since this defaults to window:
function another() {
this.foo = 'another test';
}
another();
console.log(window.foo);
edit:
// define function object window.first:
function first() {
this.foo = 'first';
}
// define function object window.second:
function second() {
this.foo = 'second';
}
// call window.first, sets window.foo to 'first':
first();
// set window.bound to a new function object which
// runs second in the context of the object first:
var bound = second.bind(first);
// call window.bound, which sets window.first.foo to 'second':
bound();
// call second, which sets window.foo to 'second' then logs the return
// value of second, which is undefined:
console.log('second: ', second());
When I run in the console, I don't quite follow why it yields a result of zero. I thought both MyObject and myFunc are global. What concept am I missing to understand this properly?
myObject = {
length: 400,
};
function myFunc () {
return console.log(this.length);
}
myFunc(myObject.length); // equals zero
It's showing you the value of window.length (which is the number of frames/iframes in the document). To have myFunc show you the value of the length of the object you pass into it, you'd have to use that argument:
function myFunc (obj) {
return console.log(obj.length);
}
If you're trying to explore implicit globals (your myObject is an implicit global; they're a Bad Thing(tm)), then myFunc should be called with no arguments and should use myObject.length or possibly this.myObject.length (which come to the same thing).
You're passing the object as a parameter, but you're not receiving it in the function. this in the context of myFunc is not the object myObject. It is the window object.
To achieve what you're trying to do, modify your code like so:
myObject = {
length: 400,
};
function myFunc (obj) {
return console.log(obj.length);
}
myFunc(myObject); // equals zero
Note:
To verify that this is the window object, see this fiddle where I've modified your console line to be return console.log(this);. The console outputs the Window object.
Demonstration Fiddle
I have the following error when running the page below:
"this.testpublic is not a function"
test = function() {
var testprivate = function() {
this.testpublic();
}
this.testpublic = function() {
console.log('test');
}
testprivate();
}
new test();
Apparently when testprivate is called, "this" starts pointing to "window" instead of the object.
Shouldn't JavaScript preserve "this" context when within the same object?
You need to manipulate the context when calling testprivate. You can use function.call to override the scope of the function. Try this:
test = function() {
var testprivate = function() {
this.testpublic();
}
this.testpublic = function() {
console.log('test');
}
testprivate.call(this);
}
new test();
The problem is that this actually never was referring to the test object to begin with. It was always referring to the nearest enclosing object -- which in this case is window.
test = function() {
var testprivate = function(say) {
console.log('test', say);
}
this.testpublic = function(say) {
testprivate('test', say);
}
testprivate();
}
x = new test();
This works because, as I understand it, this is determined at call time -- and it is locked into the nearest "enclosing" object*, unless call() or apply() is used.
* There is probably a much better word for this, but I don't know it off the top of my head. If someone knows, please enlighten us all :-)
No, it shouldn't. The function merely defines scope.
When you call foo.bar() then this (inside bar()) is foo. Since there is no explicit foo in this case, it is window by default.
(this is handled differently when the new keyword is in play, but it isn't for that call)
It is as Sean says: you aren't actually creating a new reference to an object (creating a this context), because you are simply calling the constructor - not utilizing the constructor to create a new object. If you use the new keyword, it works just peachy.
Since the scope of test() is window when you call it, any function called from within test() will execute in the window scope.
By using the new keyword, you are allocating a new object to memory - and creating a new scope.
For example, try this in firebug:
var myFunction = function() {
this.memberVariable = "foo";
console.log(this);
}
myFunction();
console.log(window.memberVariable);
var myObject = new myFunction();
console.log(myObject.memberVariable);
You will see this result:
Window stats
foo
Object { memberVariable="foo"}
foo
The Function base object has a method, call(), which as outlined by Craig, allows you to explicitly specify which scope the function should run in:
var myFunction = function() {
this.memberVariable = "foo";
}
myFunction.call(myFunction);
console.log(myFunction); // "Function()"
console.log(myFunction.memberVariable); // "foo"
This is, however, not the preferred way of doing things, as you aren't actually creating a new object here, and typeof myFunction will still return "function" instead of "object" - when you really just wanted to create an object.
What is the difference between these?
var a = 13;
this.b = 21;
document.write(a);
document.write(b);
For global code (code that is not part of any function), they are almost equivalent, both at the end create a property on the global object.
The difference is that a, which has been declared with the var statement, the Variable Instantiation process will use the global object as the Variable Object (1), and it will define that property as non-deleteable on it, e.g.:
var a = 13;
delete a; // false
typeof a; // "number"
Then, b since the this value in global code, points to the global object itself, will be also a global property, but this one can be deleted:
this.b = 21;
delete b; // true
typeof b; // "undefined"
Don't try the first snippet in Firebug, since the Firebug's console runs the code internally with eval, and in this execution context the variable instantiation process behaves differently, you can try it here.
(1) The Variable Object (VO) is an object that is used by the variable instantiation process to define the identifiers of FunctionDeclarations, identifiers declared with the var statements, and identifiers of function formal parameters, in the different execution contexts, all those identifiers are bound as properties of the VO, the Scope chain is formed of a list of VO's.
For global code, the VO is the global object itself, that's why a ends being a property of it. For function code, the VO (also known as the Activation Object for FunctionCode), is a new object is created behind the scenes when you invoke a function, and that is what creates a new lexical scope, in short I'll talk about functions.
Both a and this.b can be resolved simply as by a and b because the first object in the scope chain, is again the global object.
Also, I think is work knowing that the Variable Instantiation process takes place before than the code execution, for example:
alert(a); // undefined, it exists but has no value assigned to it yet
alert(b); // ReferenceError is thrown
var a = 13;
this.b = 21;
These differences may be trivial but I think is worth knowing them.
Now, if the code snippet you posted is within a function, it is completely different.
The a identifier, declared with the var statement in your example will be a local variable, available only to the lexical scope of the function (and any nested functions).
Keep in mind that in JavaScript blocks don't introduce a new scope, only functions do, and to declare a variable in that scope, you should always use var.
The this.b identifier will become a property bound to the object that is referred by the this value, but... What is this???.
The this value in JavaScript is implicitly set when you call a function, it is determined by how do you invoke it:
When you use the new operator, the this value inside the function, will point to a newly created object, e.g.:
function Test() {
this.foo = "bar";
}
var obj = new Test(); // a new object with a `foo` property
When you call a function that is member of an object, the this value inside that function will point to the base object, e.g.:
var obj = {
foo: function () {
return this == obj;
}
};
obj.foo(); // true
When you invoke a function without any base object, the this value will refer to the global object:
function test() {
return this == window;
}
test(); // true
The this value can be set explicitly, when you invoke a function using call or apply:
function test() {
alert(this);
}
test.call("hello world!"); // alerts "hello world!"
To understand in short, if you use these in a function then -
this.a; //will create a public property
var b; //will create a member variable
e.g. here is a Student class in javascript
var Student = function()
{
// Member variable
var studentId;
// Public property
this.Name = "";
}
for more - See Object Oriented Programming with JavaScript