When I declare a new object type :
var MyType = function(constructorArg) {
this.whatever = constructorArg;
};
var myTypeInstance = new MyType('hehe');
In that case, this refers to the function assigned to MyType.
Now let's add a simple accessor for the property whatever (without using the prototype) :
var MyType = function(constructorArg) {
this.whatever = constructorArg;
this.getWhatever = function() {
// Here this should logically point to the function assigned
// to this.whatever instead of the current instance of MyType.
return this.whatever;
};
};
This works right ?
But why isn't this, inside the body of the function assigned to the property whatever, not pointing to that function itself ?
Thanks for your help !
EDIT : I'll modify my example :
var MyType = function(arg) {
this.property = arg;
this.MySubType = function(subTypeArg) {
this.subTypeProperty = subTypeArg;
// What is "this" refereing to here ?
// To the instance of MyType, or to the instance of MySubType ?
// I know it would not make sense to do something like this in real world
// but i'm trying to have a clearer understanding of the way "this" is set.
};
}
EDIT : As said in the comments :
When using
myTypeInstance.MySubType('hehe');
then this refers to myTypeInstance.
When using
var mySubTypeInstance = new myTypeInstance.MySubType('hehe');
then this refers to mySubTypeInstance
If i understood well.
Regarding your edit, it is like it always is: It depends on how you call this.MySubType.
If you call it as this.MySubType(), i.e. as object method, then this (inside the function) would refer to this (outside the function), which is an instance of MyType.
If you call it as new this.MySubType() then it refers to a new instance of MySubType.
If you call it as this.MySubType.call(foo), this refers to foo.
Have a look at the MDN documentation, section "Function context".
I don't think this gets a new value assigned to it inside an anonymous function. You might want to look this page.
The inner function can be accessed only from statements in the outer function.
The inner function forms a closure: the inner function can use the arguments and variables of the outer function, while the outer function cannot use the arguments and variables of the inner function.
My guess would be that this must be accessable from inside the inner function and as such will not be overwritten.
Edit: I did not see the comments while typing, Felix Kling explains it much better in his comment.
Related
Is it safe to use the keyword "this" to create new Locker? I am afraid that "this" may point to something else at the runtime. I am new to JavaScript and closures.
var Employee = function() {
this.initialize.apply(this, arguments);
};
_.extend(Employee.prototype, {
initialize : function(opts) {
this._locker = new Locker({
employee : this
});
// OR
var self = this;
this._locker = new Locker({
employee : self
});
}
});
Looking at this code in particular:
this._locker = new Locker({
employee : this
});
Assuming that this already points to the right object, the above doesn't introduce a new scope; it would be the same as writing:
var options = {
employee : this
};
this._locker = new Locker(options);
You don't need to use self in this case.
You will have seen self used when someone wishes to pass the value of this into a different scope as a closure.
var self = this;
var myFunc = function() {
// do something with self (aka this)
};
In the example above this inside myFunc won't be known until the function is invoked - google 'dynamic vs static scoping' - and it won't be the 'this' from outside of the function. That this is passed through as self in my example.
Note: that you don't have to use self any other variable name will do.
In your example you aren't attempting to pass this into a different scope so it should be fine.
Both snippets act the same.
The value of this is determined by how a function is called, so you are right in that this may point to something else at runtime.
However, once initialize has been called the value of this for that call has already been set. So:
var self = this;
this._locker = new Locker({
employee : self
});
Just adds an intermediate step, assigning this to a temporary variable (see Jack's) answer
Your safer bet would be to use "this," since you are using apply and passing "this." Apply will force "this" keyword to be the thisArg that you passed to the function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
"self" is set to the Window object earlier in the initialization, but I don't think it changes after, unless you specifically change it.
Is it safe to use the keyword "this" to create new Locker?
Yes.
> var Employee = function() {
> this.initialize.apply(this, arguments);
> };
Within a function called with new (i.e. called as a constructor), this will always point to the new instance. Using apply means that arguments is not passed as an Object, but as a sequence of values. So I think you should be doing:
function Employee () {
this.initialize(arguments);
}
Note that function declarations are less code and more reliable than function expressions.
> _.extend(Employee.prototype, {
> initialize : function(opts) {
Since you are calling this with apply and using arguments as the parameter object, the arguments are passed individually by value. So opts will be the first value of the arguments originally passed to the Employee constructor, the others will be available as members of this new function's arguments object.
>
> this._locker = new Locker({
> employee : this
> });
> }
The value of this is set when a function is called (or by bind). In this case, initialize is intended to be called as a method of an instance so this will reference the instance. It could be called some other way so this references some other object (or any value if in strict mode), but the following has no effect on that.
This code doesn't make any difference to the value passed to Locker:
> var self = this;
> this._locker = new Locker({
> employee : self
> });
You seem to be trying to avoid a closure, but there is no closure here to avoid. Closures aren't caused by a function call, but by functions returning other functions that are created within them (through declarations or expressions). These functions continue to have access to the outer function's lexical environment after they have completed, e.g.
var foo = (function() {
var bar = 'bar';
return function(){ return bar;};
}());
foo(); // bar
The function foo has a closure to the variable bar declared in an outer function. No other function can access bar to read or set its value, it's only available to foo (this is how private members are emulated in javascript).
Where you run into trouble is where the value of the variable held in the closure is unexpectedly changed after the closure has been formed. That will not happen in the original code.
I write the code as follows,
function Myfunction(){
Myfunction.myvar = "somevar";
}
After I execute the function, I can able to access Myfunction.myvar
How is it working? And If I do so, What is the problem hidden in this?
If any problem, please explain context of that.
Since the function does not execute until you call it, Myfunction.myvar is not evaluated immediately.
Once you call it, the function definition has been installed as Myfunction, so that it can be resolved when you do call it.
Something like the following would not work:
var x = {
foo: 1,
bar: x.foo } // x does not exist yet.
How is it working?
When you declare a function in some execution context, a binding is added to the variable environment of that context. When you reference an identifier, the current variable environment is checked to see if a binding exists for that identifier.
If no binding exists, the outer variable environment is checked, and so on, back up to the global scope.
So:
// OUTER SCOPE
// Binding exists for 'example'
function example() {
// INNER SCOPE
// No binding for 'example'
// References 'example' in outer scope
example.x = 1;
}
What is the problem hidden in this?
There are none (in general... although whether it's the right solution for you depends on what you're trying to do).
You are effectively creating a "static" property of the function. As JavaScript functions are first-class you can set properties on them as you would with any other object.
Note that the behaviour is different if you have a named function expression, rather than a function declaration:
var x = function example () {
// Identifier 'example' is only in scope in here
};
One problem you might get because of scoping, as a more complicate example shows:
function Other() {
console.log("a) Other.Myvalue",Other.Myvalue);
Other.Myvalue=typeof Other.Myvalue==='undefined' ? 0 : Other.Myvalue+1;
console.log("b) Other.Myvalue",Other.Myvalue);
}
Other();
Other();
this would lead to
a) Other.Myvalue undefined
b) Other.Myvalue 0
a) Other.Myvalue 0
b) Other.Myvalue 1
so you realy bind your variable Myvar to the function object itself which is a singleton and exists just once (and is created by the function definition itself in the current context which may be the global context), not to an instance of that object. But if you just use static values and don't need any logic, it's like the literal form, and I wouldn't expect any problems, other that the literal form is more convenient:
var Other = {
Myvalue: "somevalue"
};
In javascript every function is an object. So you can add any custom fields to it.
function A() {}
A.somevar = 'this is custom field';
A.prototype.somevar2 = 'this is field in A proto';
So when you will create new object with A contructor it will take properties from prototype.
var b = new A();
alert(b.somevar2);
first using var
function testCode(some)
{
var something = some;
}
the second using this
function testCode2(some)
{
this.something = some ;
}
In the first function, something is a private (local) variable, meaning it will be completely inaccessible outside the function; whilst in the second it's a public instance variable. The context on which the variable will be set will depend on how you invoke the function:
> testCode2("foo"); // this will refer to document.window
> something
"foo"
>> var obj = new testCode2("foo"); // this will refer to the new object
>> something
ReferenceError: something is not defined
>> obj.something
"foo"
Reference:
Private Members in JavaScript, by Douglas Crockford
If those functions are used as functions, the this keyword will make the variable static. If the function is called twice, this.something will still have its value while the first subject will erase the variable data once the function has finished executing.
If you are using them as class constructors, var will define a private variable and this will declare a public variable.
See this fiddle: http://jsfiddle.net/UUFuX/1/
This code results in "!" being logged on the console.
var g = {};
(function() {
var t = this;
t.x = "x";
g.a = function() {
console.log(t.x);
};
})();
(function() {
var t = this;
t.x = "!";
g.b = function() {
console.log(t.x);
};
})();
g.a();
Do anonymous functions share a this? Am I using this wrong? I don't really understand what's going on here.
I'd like for g.a() to continue returning the value of x defined in the first anonymous function.
I'm using node.js if it makes a difference.
In the immediate functions, this refers to the global object [docs]. So in this case in both functions this indeed refers to the same element and you are overwriting x with the second call.
What object this refers to is determined by how the function is called.
If you just execute a function with funcName();, then this refers to the global object.
If the function is assigned to a property of an object, obj.funcName() , this refers to the object.
If you call the function with the new operator, new funcName();, this refers to an empty object that inherits from the functions prototype.
You can also explicitly set this by using call [docs] or apply [docs].
Instead referring to this, you could create a new object in both functions:
var t = {};
Additional note: It makes no difference whether you run the code in the browser or with node.js. The global object is part of the specification and has to be provided by the execution environment. In browsers it is the window object, I don't what it is in node.js, but it does not matter as long as it follows the specification.
Felix Kling is the right long answer. But I wanted to chime in with what I think you actually want:
var g = {};
(function() {
var x = "x";
g.a = function() {
console.log(x);
};
})();
(function() {
var x = "!";
g.b = function() {
console.log(x);
};
})();
g.a(); // "x"
g.b(); // "!"
Now g.a() and g.b() both print out x, but each function has their own separate x shared with the closure. If these vars should be private an only accessible internally to each of these functions, this is how you hide them and persist them through multiple calls.
When I look at this script in the debugger in Chrome as you've shown it, the "this" value in both anonymous functions is set to the global variable "window". That means that each anonymous function is setting the value of window.x so the last one executed wins and is the value that survives, thus window.x == "!" after the second anonymous function executes.
It's unclear to me what you expected "this" to be or what you're actually trying to accomplish with this code so I don't know what alternative to suggest. If you just want the previous state in the anonymous function to survive for the internal function, then you can just rely on local variables (which will survive in the closure) and not use the "this" reference at all. Squeegy's example shows that.
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
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 nick if there isn't one with a non-falsey value already
Create an anonymous function that…
Creates a variable called helloA in its own scope
Outputs data using console.log containing "1" (as is), this (the window because the function is executing in the global context instead of as a method), and this.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 the init function in the context of name.
This defines helloB
Then it console.logs with "2" (as is), this (name), and this.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)
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
this is defined on a per-function basis when the function call is made. When you call a function as o.f(), this will be o within the function, and when you call it as f(), this will be the global object (for browsers, this is the window).
You wrote nick.name = function(){...}(); and the right-hand part is of the form f(), hence the Window.
var foo = bar; defines a local variable. It may not be accessed as this.foo (well, except when you're at global scope, but that's silly). To define a member, you usually write this.foo = bar; instead.
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 init property) to the name property of the object.
It gets the value from the init property, which is a method delegate, and calls the method.
The anonymous function does this:
It declares a local variable named helloA and 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 the helloA property (which doesn't exist).
It creates an anonymous function and assignes to the local variable init.
It creates an object with the property init and the value from the local variable init.
The anonymous function assigned to the init property does this:
It declares a local variable named helloB and 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 the name property, not the nick variable), and the helloB property (which doesn't exist).