3

I'm doing some testing on jQuery.data(), and I'm trying to create a local reference to a certain data-key, which I hopefully can change locally and still affect "outside". I think it would be better with an example, due to the semi-long code I posted it on jsFiddle instead of here:

http://jsfiddle.net/esbenp/p4kt2/22/

the output I hope for is:

{1: {length: 1}, total: 1}

but only the length property is affected by incrementing the local variable:

{1: {length: 1}, total: 0}

what should I do?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Esben
  • 1,943
  • 1
  • 18
  • 37
  • I believe you're seeing [variable shadowing](http://en.wikipedia.org/wiki/Variable_shadowing) caused by the fact that the local variable has the same name as the outer variable which you're trying to affect. – Matt Ball Apr 22 '11 at 20:25
  • if i understand this correctly, you are suggesting i change the local variable total to something else like total_errors, so it's name isn't the same as the one in the $.data object? If so - i gave it a try, but it did not work : – Esben Apr 22 '11 at 20:42

2 Answers2

5

If you store an object (or array) in .data() then you're actually storing a reference to it, so if you do:

var obj = { key: 'value' }
$(el).data('obj') = obj;
obj.key = 'new value';

$(el).data('obj').key will also be new value, because it's the same object.

However if the value stored is a plain type instead (e.g. a number or a string) that a copy of it will be stored:

var n = 5;
$(el).data('obj') = n;
n++;

$(el).data('obj') will still be 5.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
2

I am not going to lie - that code is incredibly confusing. Is there a reason why you need to use all those self-executing functions? It seems (at least to this layperson) that you could code this in a much more straightforward way to achieve your goal.

Anyway I am not sure this is the answer you're looking for, but I just stopped the debugger inside AddError so I could understand its scope and what was available. So all you need to do to make it return the output you want is this:

http://jsfiddle.net/qN7wF/2/

functions = {
    AddError: function() {
        console.log(total);
        $(container).data('errors').total++;
        errors.length++;
  },

But given the context... I'm guessing there must be more at play.

Jamie Treworgy
  • 23,934
  • 8
  • 76
  • 119
  • Yes, it is quite confusing for such a simple goal. It's because im doing this in an application with much more code, so i just removed all the irrelevant code. The self-executing funtions, was the only way to get it to work :) if you have a simpler solution for adding 1: {length:0} key and creating the local variable i would love to hear it. I was aware that i could do it with $(elem).data, but i would like to do it with $.data(elem), the performance difference is supposed to be big (or so i've read :)) – Esben Apr 22 '11 at 20:53
  • I have actually been futzing around with `$.data` a bit lately for a plugin I'm working on, and I think that I'm going to ditch it entirely. That is, I think the primary benefits (other than convenience) are when you need to persist data between isolated parts of an app (e.g. separate modules). Within a given module I don't see any benefit versus just using your own storage mechanism (e.g. an array of objects), as long as you have some identifier other than the DOM element itself. Cheap hack: store the array index in a custom attribute on the element for o(1) lookup time, given an element. – Jamie Treworgy Apr 22 '11 at 21:06