How to pass by items by value from an array to a variable in Javascript
-
05-07-2019 - |
Question
I'm trying to loop through an array "fSel.sI", and based on the data inside, pass them as values (not reference) on to a number of function declarations. Right now the problem is that mydrag contains a reference, and as draggable gets called it uses the last array item data. Hence when start: drag: stop: is called, the values are not unique. Help?
makeDraggable : function() {
// create new draggable
for (var i = 0; i < fSel.sI.length; i++) {
mydrag = fSel.sI[i];
$("#" + mydrag).draggable({
cancel: [''],
distance: 5,
containment: "#fWorkspace",
handle: mydrag,
start: function() { dragRegister(mydrag)},
drag: function() { dragItems(mydrag)},
stop: function() { dragStop(mydrag)}
});
}
},
Solution
You should look into closures.
Try the following code:
makeDraggable : function() {
// create new draggable
for (var i = 0, l = fSel.sI.length, sI = fSel.sI; i < l; i++) {
var mydrag = sI[i];
(function(mydrag) {
$("#" + mydrag).draggable({
cancel: [''],
distance: 5,
containment: "#fWorkspace",
handle: mydrag,
start: function() { dragRegister(mydrag); },
drag: function() { dragItems(mydrag); },
stop: function() { dragStop(mydrag); }
});
})(mydrag);
}
},
Your problem is with the start
, drag
, and stop
functions. They don't execute immediately; by the time they do, mydrag
has been set to another value. By wrapping a self-executing function around the code block containing these functions, we create a closure, where mydrag
doesn't change.
Note: For performance reasons, when accessing properties of an object more than once, it's best to create a variable that references (or holds) the property. In your for
loop, I've created two variables l
and sI
that store fSel.sI.length
and fSel.sI
(respectively) so that JavaScript doesn't have to look up the sI
and length
properties every time around the loop.
OTHER TIPS
This is because your creating a closure. Try this instead
makeDraggable : function() {
// create new draggable
for (var i = 0; i < fSel.sI.length; i++) {
mydrag = fSel.sI[i];
$("#" + mydrag).draggable({
cancel: [''],
distance: 5,
containment: "#fWorkspace",
handle: (function(mydrag){return mydrag;}(mydrag)),
start: (function(mydrag){return function() { dragRegister(mydrag)};}(mydrag)),
drag: (function(mydrag){return function() { dragItems(mydrag)};}(mydrag)),
stop: (function(mydrag){return function() { dragStop(mydrag)};}(mydrag))
});
}
},
Take a look at this video to understand the powerful and usefulness of Javascript closures: http://vimeo.com/1967261