I've been reading through quite a few articles on the 'this' keyword when using JavaScript objects and I'm still somewhat confused. I'm quite happy writing object orientated Javascript and I get around the 'this' issue by referring the full object path but I don't like the fact I still find 'this' confusing.
I found a good answer here which helped me but I'm still not 100% sure. So, onto the example. The following script is linked from test.html with <script src="js/test.js"></script>
if (!nick) {
var nick = {};
}
nick.name= function(){
var helloA = 'Hello A';
console.log('1.',this, this.helloA);
var init = function(){
var helloB = 'Hello B';
console.log('2.',this, this.helloB);
}
return {
init: init
}
}();
nick.name.init();
What kind of expected to see was
1. Object {} nick.name, 'Hello A'
2. Object {} init, 'Hello B'
But what I get is this?
1. Window test.html, undefined
2. Object {} init, undefined
I think I understand some of what's happening there but I would mind if someone out there explains it to me.
Also, I'm not entirely sure why the first 'console.log' is being called at all? If I remove the call to the init function //nick.name.init() firebug still outputs 1. Window test.html, undefined. Why is that? Why does nick.name() get called by the window object when the html page loads?
Many thanks
4 Answers 4
Also, I'm not entirely sure why the first 'console.log' is being called at all?
nick.name = function(){
// ...
}();
Here you define a function, call it immediately (hence ()) and assign its return value ({init: init}) to nick.name
So the execution is:
- Create a variable called
nickif there isn't one with a non-falsey value already - Create an anonymous function that...
- Creates a variable called
helloAin its own scope - Outputs data using
console.logcontaining "1" (as is),this(thewindowbecause the function is executing in the global context instead of as a method), andthis.helloA(window.helloA, which doesn't exist. - Defines a function called
init - Returns an object which gets assigned to
nick.name - Then you call
nick.name.init()which executes theinitfunction in the context ofname. - This defines
helloB - Then it
console.logswith "2" (as is),this(name), andthis.helloB(nick.name.helloB- which doesn't exist)
So the first output you get is from console.log('1.',this, this.helloA);
I think your main problem is that you are confusing this.foo (properties on the object on which a method is being called) with variable scope (variables available to a function)
2 Comments
helloB in the context of lowman. It defines in the scope of lowman. A variable existing in a given scope is not the same as a property on an object.It's much simpler if you think about this as a function, not as a variable. Essentially, this is a function which returns current "execution context", that is, the object the current function was "applied" to. For example, consider the following
function t() { console.log(this)}
this will return very different results depending upon how you call it
t() // print window
bar = { func: t }
bar.func() // print bar
foo = { x: 123 }
t.apply(foo) // print foo
2 Comments
thisis defined on a per-function basis when the function call is made. When you call a function aso.f(),thiswill beowithin the function, and when you call it asf(),thiswill be the global object (for browsers, this is the window). You wrotenick.name = function(){...}();and the right-hand part is of the formf(), hence theWindow.var foo = bar;defines a local variable. It may not be accessed asthis.foo(well, except when you're at global scope, but that's silly). To define a member, you usually writethis.foo = bar;instead.
2 Comments
this is the global object, which for web browsers is Window.This is what your code does:
- It creates an object and assigns to the variable
nick. - It creates an anonymous function.
- It calls the function (in the window scope).
- It assigns the return value (an object containing the
initproperty) to thenameproperty of the object. - It gets the value from the
initproperty, which is a method delegate, and calls the method.
The anonymous function does this:
- It declares a local variable named
helloAand assigns a string to it. (Creating a local variable doesn't add it as a property to the current object.) - It logs
this(window) and thehelloAproperty (which doesn't exist). - It creates an anonymous function and assignes to the local variable
init. - It creates an object with the property
initand the value from the local variableinit.
The anonymous function assigned to the init property does this:
- It declares a local variable named
helloBand assigns a string to it. (Creating a local variable doesn't add it as a property to the current object.) - It logs
this(the object from thenameproperty, not thenickvariable), and thehelloBproperty (which doesn't exist).
2 Comments
this keyword to access the object. If it's the default context (window) you will be adding properties to the window object, thus making them global/public.