Reputation: 148524
I'm breaking my head here. I have this simple code :
function myFunc()
{
this.a = "aaa";
return {
h: function ()
{
alert(this.a);
}
}
}
var f = new myFunc();
console.log(f.h.apply(f)) //I'm expecting to see here : "aaa" but it says "undefined"
f.h
look exactly like this :
function ()
{
alert(this.a);
}
And so , i'm trying to set context to f
itself (which contains the a
prop) via apply
.
But it doesn't work.
What am I missing ?
p.s. there are other alternatives. I know. but why my specific code doesn't work ?
Upvotes: 1
Views: 110
Reputation: 13994
f
does not contain a, since you return an arbitrary object that 'overwrites' the default object that would otherwise have been returned, and that would have contained a.
If you used
function myFunc() {
return {
a:"aaa",
h:function() { alert this.a; }
}
}
then it would work!
If you want to use 'private' and 'public' variables then make it like this
function myFunc() {
var a = "aaa";
return {
h:function() { alert a; }
}
}
Upvotes: 6
Reputation: 1253
First, keep track of how you're returning and printing items. You're attempting to use both alert
and console.log
for this job when you should be only using one. In addition, you're attempting to console.log
the return value of a function that doesn't return anything. For my example below, I chose to use console.log
and kept the function returning nothing. Below, I fixed this first problem:
function myFunc() {
this.a = "aaa";
return {h: function () {console.log(this.a);}}
}
var f = new myFunc();
f.h.apply(f);
Now onto the real problem. this.a
returns undefined
because this
is bound to different two different things (first an instance of myFunc
, and then f
) the two times you use it in your code. You can use console.log(this)
to verify this.
To solve this problem, bind a variable (let's call it self
) to this
so that you can reference it later. In JavaScript, inner functions have access to variables bound in outer functions. (This is called closure.) This allows us to use self
in the following way:
function myFunc() {
var self = this;
this.a = "aaa";
return {h: function() {console.log(self.a);}}
}
var f = new myFunc();
// f.h.apply(f); // replaced by next line; see first comment
f.h();
This prints the line aaa
to the console.
Upvotes: 1
Reputation: 700212
When you are returning an object from the function you are getting that object instead of the object that was created by the ˋnewˋ keyword. The object where you put the ˋaˋ property doesn't exit any more.
Put the method in the object that is created instead of creating a different object:
function myFunc() {
this.a = "aaa";
this.h = function () {
alert(this.a);
}
}
Now the object contains the property, so you don't need to use apply to get the right context:
var f = new myFunc();
console.log(f.h())
Upvotes: 2
Reputation: 388316
If you want to use closure, create a
as a local variable. This will make a
as a private property which outside world will not be able to access directly
function myFunc(){
var a = "aaa";
return {
h: function () {
alert(a);
}
}
}
var f = new myFunc();
console.log(f.h(f))
Demo: Fiddle
Upvotes: 5
Reputation: 483
You are losing scope with the closure, try this:
function myFunc()
{
this.a = "aaa";
that = this;
return {
h: function ()
{
alert(that.a);
}
}
}
var f = new myFunc();
console.log(f.h.apply(f))
Upvotes: 0