Access Object's "this" in another object's foreach function? - javascript

function Test(){
this.update = function(entity){
entity.forEach(function(enemy) {
this.checkHit(enemy);
});
}
this.checkHit = function(entity){
console.log("worked!");
}
}
How can I call Test's this.checkHit function, and pass it the current value in the entity's foreach loop?
Current code gives "this.checkHit" is not a function.

If you don't care about old browsers - which seems to be the case since you're using forEach - you could use bind (also I assume that you're doing new Test() somewhere) :
entity.forEach(function (enemy) {
this.checkHit(enemy);
}.bind(this));

Just put this in a normal variable. self is commonly used
function Test(){
var self = this;
this.update = function(entity){
entity.forEach(function(enemy) {
self.checkHit(enemy);
});
}
this.checkHit = function(entity){
console.log("worked!");
}
}

Related

Using Constructor variables during the instantiation

Is it possible, while creating an instance of an object, to check during the instantiation itself the type of the parameter passed to the constructor, and set one of the object's variable accordingly?
This is what I'm trying to do:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = (function() {
console.log(this.num1); // logs "undefined" upon instantiation
if (isNaN(this.num1)) {
return false;
} else {
return true;
}
}());
}
var testObj = new Test(5);
I want isValidNumber's value to be true or false according to the parameter passed to the constructor.
Your IIFE (Immediately-Invoked Function Expression) creates a new context, which means this doesn't point to your constructor anymore but to the Window object (unless you're using strict mode which would make it undefined). One possible solution is to execute this function with the right context:
this.isValidNumber = function() {
if (isNaN(this.num1)) {
return false;
} else {
return true;
}
}.call(this);
The much simpler solution is obviously:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = !isNaN(this.num1);
}
First of all, the code could (and probably should) be rewritten the following way:
function Test(num1) {
this.num1 = num1;
console.log(this.num1);
this.isValidNumber = !isNaN(this.num1);
}
As for the reason why your code is not working as expected – your self invoking function has its own this parameter which is unrelated to the this parameter within your constructor.
In this case the this parameter of your self invoking function references the global object. (In strict mode it would've been undefined)
If you really need to reference the this parameter of a containing function then there are several ways to achieve this, the simplest of which being:
function Test(num1) {
this.num1 = num1;
var self = this;
this.isValidNumber = (function() {
console.log(self.num1);
return !isNaN(self.num1));
}());
}
In your particular case you don't even need to capture it, and this would also achieve the same effect:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = (function() {
console.log(num1);
return !isNaN(num1));
}());
}
But again, the self invoking function is simply not required here.
This in the inner function no longer references the parent object. A common way of storing the object reference is to create a 'self' variable and assign this to it when it's in the correct scope
function Test(num1) {
var self = this;
this.num1 = num1;
this.isValidNumber = (function() {
console.log(self.num1);
if (isNaN(self.num1)) {
return false;
} else {
return true;
}
}());
}
var testObj = new Test(5);

Access variable within callback function

Hi I have the following code where I am calling a function that takes a callback function that takes a parameter. Basically I am trying to get the contents of e into this.items but I cant escape the callback function?
function stash(){
this.items = new Array();
this.get = function(){
opr.stash.query({},function(e){
console.log(this.items); //this is not defined
});
}
}
s = new stash();
s.get();
Problem: callback function's context object (this) no longer refers to the context object of get() method.
Solution: bind your callback function to the target object, like this:
opr.stash.query({},(function(e){
console.log(this.items);
}).bind(this));
this is no longer in scope on the callback so make a reference to it that you can user later. The .bind(this) is a good solution in modern browsers but may fail in older versions of Internet Explorer as that method may not be available.
function stash(){
var self = this;
this.items = new Array();
this.get = function(){
opr.stash.query({},function(e){
console.log(self.items);
});
}
}
I ran into a similar problem in d3.chart.
I don't have access to opr.stash at the moment so i couldn't test this first, but have you tried something like the following:
function stash()
{
var myStash = this;
myStash.items = new Array();
myStash.get = function(){
opr.stash.query({},function(e){
console.log(myStash.items); //this is not defined
});
}
}
s = new stash();
s.get();

Access values of object from within a javascript closure

I can't get how to access that value, this is my code:
function Filters()
{
this.filters = ["filter_1", "filter_2", "filter_3"];
this.someData = "test";
this.draw = draw;
function draw(){
for(var i=0; i<this.filters.length;i++)
{
var filter = this.filters[i];
$("#" + filter).click(function(){
doSomething();
});
}
}
function doSomething(){
alert(this.someData);
}
}
I am aware of the fact that since doSomething() is called from within the closure, this. will refer a JQuery object being worked on. So how do I go about being able to use someData from my object in that function/closure ? Can't seem to figure it out.
Thanks for help :)
No, this inside doSomething will be the global object. You need to keep a reference to this in a separate variable:
function Filters()
{
var that = this; // reference to this
this.filters = ["filter_1", "filter_2", "filter_3"];
this.someData = "test";
this.draw = draw;
function draw(){
for(var i=0; i<this.filters.length;i++)
{
var filter = this.filters[i];
$("#" + filter).click(function(){
doSomething();
});
}
}
function doSomething(){
alert(that.someData);
}
}
Unrelated to your problem: you could also pass a reference to doSomething as the event listener, instead of wrapping it in another function:
$("#" + filter).click(doSomething);

Javascript - revealing object and variable scope

http://jsfiddle.net/ZLH7J/1/
What the jsFiddle and code below shows are two examples that essentially do the same thing. When trying to call first(); or this.first(); in either example, an undefined error is thrown. I can call the functions later through the instance, but not when trying to instantiate the object using init(){...}() like a constructor. I put init() at the bottom thinking it was an order of operations thing, but that is not the case. This does not work the way I thought it would work.
I am curious to understand how this is supposed to be done, and why this cannot be done.
//create and return an obj
var fishSticks = function(){
return {
first: function(){
document.getElementById('output').innerHTML="Success";
},
init: function(){
try{
first(); //err
this.first(); // also err
}catch(e){
document.getElementById('output').innerHTML=e.toString();
}
}()
}
}
//do function stuff and then return 'this'
var fishFillet = function(){
var first = function(){
document.getElementById('output2').innerHTML="Success";
}
var init = function(){
try{
first(); //err
this.first(); // also err
}catch(e){
document.getElementById('output2').innerHTML=e.toString();
}
}()
return this;
}
var test = new fishSticks();
var test2 = new fishFillet();
​
You need to understand two things:
1) JavaScript does not automatically insert this like Java does, so the first() call will only look through the lexical scope for a definition of first, it will nok look at the this object. Therefore the call to first() should work but this will be bound to something else than what you might expect inside first.
2) Local variables in a constructor do not become members of the constructed object.
In your second example, if you comment out the call in "init" to this.first() then you get the "Success" message.
The first version doesn't work because JavaScript simply does not allow for references to be made within an under-construction object to the object itself. There's just no way to do it.
The second one works (well the simple reference to "first" works) because "first" is declared as a local variable. Local variables are not properties of any object, and in particular they're not properties of the object allocated when the function is called with new. That's why this.first() doesn't work.
In the second one, you could make this.first() work by declaring things differently:
var fishFillet = function(){
this.first = function(){
document.getElementById('output2').innerHTML="Success";
}
var init = function(){
try{
this.first(); //will work
}catch(e){
document.getElementById('output2').innerHTML=e.toString();
}
}()
return this;
}
Also, for what it's worth, the weird anti-pattern of
var something = function() { ... }
is not as useful as
function something() { ... }
There's no reason to use the var declaration instead of the function declaration.
How about...
var fishFillet = function () {
var first = function () {
document.write( 'Success' );
};
var init = function () {
first();
};
init();
return {
first: first
};
};
And then:
var ff = fishFillet(); // calls init() which calls first()
ff.first(); // call first() manually
Live demo: http://jsfiddle.net/uaCnv/
So, first you define all your functions, next you manually invoke init, and last you return an object containing those functions which should be available through the resulting object (as methods).
Since you are using both as a constructor, format them as such:
function fishFillet(){
this.first = function(){
document.getElementById('output2').innerHTML="Success";
}
this.init = function(){
try{
this.first();
}catch(e){
document.getElementById('output2').innerHTML=e.toString();
}
}
}
var food = new fishFillet();
food.init();
The reason it wasn't working for you is b/c "first" is created as a local varaible, and is deleted after execultion. Init isn't being called until after the execution of the constructor has finished

JavaScript OOPS Question

A JavaScript newbie here. I have this following code:
function testObject(elem) {
this.test = "hi";
this.val = elem;
console.log(this.test+this.val);
echo();
function echo () {
console.log(this.test+this.val);
}
}
var obj = new testObject("hello");
When it is run, I expect "hihello" to be outputted twice in the console. Instead it outputs as expected the first time but returns NaN the second time.
I'm sure I'm missing something here. I thought that the internal function can access the vars held outside. Can someone please guide me? I'm more of a functional UI developer and don't have much experience with OO code.
Thanks!
The problem is that inside echo the this value points to the global object, and this.test and this.val (which are referring to window.test and window.val) are undefined.
You can set the this value of echo by invoking it like:
echo.call(this);
That happens because you were invoking the function by echo();, then the this value is implicitly set to the global object.
Give a look to this question to learn how the this value works.
Edit: For being able to calling just echo(); you should persist the this value from the outer function context, there are a lot of ways to do it, for example:
//...
var instance = this; // save the outer `this` value
function echo (){
console.log(instance.test+instance.val); // use it
}
echo();
//...
Or
//...
var echo = (function (instance) {
return function () {
console.log(instance.test+instance.val);
};
})(this); // pass the outer `this` value
echo();
//...
You could also do this:
function testObject(elem) {
this.test = "hi";
this.val = elem;
console.log(this.test+this.val);
this.echo = function () {
console.log(this.test+this.val);
}
this.echo();
}
var obj = new testObject("hello");
​Whenever you call this.echo() or obj.echo(), this will be bound to the object invoking the function.
Personally, I find it elegant to declare class methods like this:
function testObject(elem) {
this.test = "hi";
this.val = elem;
this.echo();
}
testObject.prototype = {
echo: function () {
console.log(this.test + this.val);
}
}
var obj = new testObject("hello");

Categories