Reputation: 13
I have this code that works perfectly well on its own :
var Person = {
getName: function() {
alert("Johnny");
}
};
var myContext = "Person";
var theCodeToExecute = myContext + ".getName()";
var theFunctionItself = new Function(theCodeToExecute);
theFunctionItself();
But when I put it inside jQuery, it stops working.
$(document).ready(function() {
//Where the code should be.
});
I'm aware that very similar questions have been answered, but none of them fixed that precise problem.
EDIT :
Thanks everyone for the answers. I guess I narrowed down my problem so much that I made my intentions very unclear. Here's a clearer version of what i'm trying to achieve :
var Road = {
House: function(color, size, neighbor){
this.color = color;
this.size = size;
this.neighbor = neighbor;
}
};
Road.House.prototype.getSize = function() {
alert(this.size);
};
Road.House.prototype.getNeighborSize = function() {
var theNeighbor = this.neighbor;
var codeToExecute = theNeighbor + ".getSize()";
var tmpFunc = new Function(codeToExecute);
tmpFunc(); //this only works when outside of jQuery.
};
var house1 = new Road.House("blue", "small", "house2");
var house2 = new Road.House("red", "huge", "house3");
house1.getNeighborSize(); //this successfully returns "huge" when outside of jQuery.
Again, this works perfectly well on its own but doesn't work within jQuery, and I need it to work within jQuery because the final version of my functions will use a lot of jQuery code. Thanks again!
LAST EDIT :
Thanks Felix for your excellent help. There seems to be one final problem. I can only get the size of a neighbor if the neighbor is declared BEFORE the house I'm querying.
var house1 = new Road.House("red", "big", house2);
var house2 = new Road.House("blue", "huge", house3);
var house4 = new Road.House("blue", "small", house4);
var house3 = new Road.House("blue", "little", house1);
house1.getNeighborSize(); //this doesn't work.
house3.getNeighborSize(); //this works
Thanks again!!
Upvotes: 0
Views: 83
Reputation: 816394
When you create a function with new Function
, it will be created in global scope.
I.e. it does not have access to the variables you created inside the ready
callback.
// global scope
$(document).ready(function() {
// ready callback scope
});
Citing the big yellow box from MDN here:
Note: Functions created with the
Function
constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called. This is different from usingeval
with code for a function expression.
Solutions:
Person
in global scope.eval
instead of new Function
.and the best of all:
Person.getName()
directly. Even if you think you'd have to evaluate code, you probably don't, but we can't help you find alternatives if you don't explain what you are really trying to achieve.
Well, the actualy to solution to your problem is not to try to refer to variables dynamically, but pass a reference to the neighbor to the constructor:
var house2 = new Road.House("red", "huge");
var house1 = new Road.House("red", "huge", house2);
Then the function would look like
Road.House.prototype.getNeighborSize = function() {
if (this.neighbor) {
this.neighbor.getSize();
}
};
If you can't pass a reference to the neighbor at construction time, you can create a setter:
Road.House.prototype.setNeighbor = function(neighbor) {
this.neighbor = neighbor;
};
Upvotes: 4
Reputation: 2312
Alright, there are a few errors here if you're trying to invoke a method. You should avoid dynamically evaluating Javascript like that, as Felix mentioned. First off I'll start with the corrected code, assuming you just wanted to invoke the getName method.
$(document).ready(function() {
var Person = {
getName: function() {
alert("Johnny");
}
};
Person.getName();
});
You do not need to re-assign Person to a new variable, you can just access it directly here. You also put Person in quotes, which means that your myContext variables referenced a string with the word "Person".
Now, what I think you actually want to do is build a constructor function, from your use of new.
Here's how that'd actually be done:
$(document).ready(function () {
//You need to make it a function that returns an object
var Person = function (name) {
return {
getName: function () {
alert(name);
}
}
};
//Then we create an instance of Person and pass in the name as an argument
var johnny = new Person('Johnny');
johnny.getName();
});
You'll see that instead of making Person an object, we made it a function that returns an object, and we used a function argument to act as a placeholder for the name. This way we can create as many people as we want, and we don't have to redefine Person every single time. For example, if we wanted to make some more people, we'd just do:
var sam = new Person('Sam');
var jim = new Person('Jim');
Now sam.getName() will alert 'Sam' and jim.getName() will alert 'Jim'.
Upvotes: 0