0

I want to:

  1. instantiate a JavaScript array of objects, where objects properties refer to other properties of the object itself, and then
  2. use the array to configure click event of a set of buttons.

problems (pls see snippet above):

  1. mymessage and myvalue parameters are undefined when anotherfunction() is called
  2. when a button of class myclass* is clicked x[i].myaction(); is undefined because at the time the button is clicked, i evaluates 2

var x = [{
  mymessage: "this is message1",
  myclass: "myclass1",
  myvalue: 10,
  myaction: function() {
    var res = anotherfunction(mymessage, myvalue);
    //do something with res
  }
}, {
  mymessage: "this is message2",
  myclass: "myclass2",
  myvalue: 20,
  myaction: function() {
    res = anotherfunction(mymessage, myvalue);
    //do something else with res
  }
}];

function anotherfunction(m, v) {
  alert(m);
  return v;
}
for (var i = 0, len = x.length; i < len; i++) {
  $('.' + x[i].myclass).click(function() {
    alert(i);
    x[i].myaction();
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="myclass1">Click me1</div>
<div class="myclass2">Click me2</div>
Roberto Vanoli
  • 441
  • 1
  • 4
  • 15
  • 1
    As per your modified version of this question. You can take `i` under a closure by the help of an IIFE inside the for loop. – Redu Nov 23 '16 at 18:17
  • I understood what you are saying, but unfortunately I'm not so practical with javascript to effectively use this pattern in above situation :-( please can you give me an example ? – Roberto Vanoli Nov 23 '16 at 18:39
  • 1
    After the edit it's a duplicate of [JavaScript closure inside loops – simple practical example](http://stackoverflow.com/q/750486/1529630) – Oriol Nov 23 '16 at 20:52
  • @Oriol: my question is about referring to other properties of the same object when it is istantiated into an array (as the title try to explain). The interesting part of the suggested solution is in my opinion, the use of the 'this' clause. The closure is adopted to _consume_ correctly such array, but the 'this' clause is the focus. – Roberto Vanoli Nov 24 '16 at 01:02

3 Answers3

2

Simply use x.mymessage and x.myvalue

var x = {
  mymessage: "this is a message", 
  myclass: "myclass", 
  myvalue: 10,
  myaction:  function() {
    anotherfunction(x.mymessage, x.myvalue); 
  }
};
function anotherfunction(m, v) {
  alert(m);
}
$('.'+x.myclass).click(x.myaction)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="myclass">Click me</div>
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Following your solution (which actually answers the original question), I realized that my question was oversimplified and I modified it – Roberto Vanoli Nov 23 '16 at 17:35
1

Just change it to the following

var x = {
  mymessage: "this is a message",
  myclass: "myclass",
  myvalue: 10,
  myaction: function() {
    anotherfunction(x.mymessage, x.myvalue);
  }
};

function anotherfunction(m, v) {
  alert(m);
}

$('.' + x.myclass).click(x.myaction);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="myclass">
  hi
</div>

Hope it helps

Geeky
  • 7,420
  • 2
  • 24
  • 50
1

For re-usability purposes you should in fact use this in the object like

myaction:  function() {
    anotherfunction(this.mymessage, this.myvalue); 
  }

However you should invoke it with the proper context in the callback of the event listener as follows;

var x = {
  mymessage: "this is a message", 
  myclass: "myclass", 
  myvalue: 10,
  myaction:  function() {
    anotherfunction(this.mymessage, this.myvalue); 
  }
};
function anotherfunction(m, v) {
  alert(m);
}
$('.'+x.myclass).click(function(e){x.myaction()})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="myclass">Click me</div>

So as per the modified version of this question, I believe it's a very good example to demonstrate the re-usability of the this in the array of objects. You can safely do as follows;

var x = [{
  mymessage: "this is message1",
  myclass: "myclass1",
  myvalue: 10,
  myaction: function() {
    var res = anotherfunction(this.mymessage, this.myvalue);
    //do something with res
  }
}, {
  mymessage: "this is message2",
  myclass: "myclass2",
  myvalue: 20,
  myaction: function() {
    res = anotherfunction(this.mymessage, this.myvalue);
    //do something else with res
  }
}];

function anotherfunction(m, v) {
  alert(m);
  return v;
}
for (var i = 0, len = x.length; i < len; i++) {
  (function(j){
     $('.' + x[j].myclass).click(function(e) {
                                   alert(j);
                                   x[j].myaction();
                                 });
   })(i);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="myclass1">Click me1</div>
<div class="myclass2">Click me2</div>
Redu
  • 25,060
  • 6
  • 56
  • 76