.data( object ) and memory-leak

.data( object ) and memory-leak

For quite some time now I had intention to open this discussion because of increasing tendency of using data/event API on native objects.

Why this is a problem?
Well, the current $.data implementation is optimized for host objects only, and not for native objects too.
In fact, it uses a cache object to store all related data and an expando with numerical values to keep references.
The need of such solution is unquestionable and it fits well because elements are normally "eliminated" by using .remove() that also cleans respective data. Native objects, in other hand, are not "eliminated" with such call, and related data exists until the window is closed.

Of course, this problem also exists with the event API, that uses data API to store handlers...

Solution A
Probably the easiest fix would consist on storing data as expando property of native objects.

  1. // ...
  2. if ( elem.nodeType ) {
  3.         cache[ id ] = dataObject;
  4.         elem[ expando ] = id;
  5. } else {
  6.         elem[ expando ] = dataObject;
  7. }
  8. // ...

Inheritance problem
Unfortunately that fix would not be sufficient once the object inheritance will become mainstream.

  1. var objA = {};
  2. var objB = Object.create( objA );

  3. $.data( objA, "foo", "bar" );
  4. $.data( objB, "foo" )  // => "bar"  -  ok, I suppose..
  5. // ..but..
  6. $.data( objB, "foo", "barB" );
  7. $.data( objA, "foo" );                     // => "barB"  -  oh noo..
  8. $.data( objA ) === $.data( objB )   // =>  true     -  ...objA and objB have the same data object!

If you think that the returned value at line 5 would be 'undefined', then using hasOwnProperty on reading objectData of native objects will resolve the problem at lines 7-9. Otherwise, keep reading.

Solution B
To inherit values of parent objects, we have to store values in native objects itself!

  1. // ...
  2. if ( elem.nodeType ) {
  3.         dataObject[ name ] = value;
  4. } else {
  5.         elem[ expando +"_" + name ] = value;
  6. }
  7. // ...

The only lack of this solution is that we can not return the data object of the native object, because it doesn't exists!

  1. $.data( objA );  // => null? there is no data objects for native objects!

But I think it's not a big deal...


EDIT: Reconsidering the first solution...