8

This is related to the question javascript cloneNode and properties.

I'm seeing the same behaviour. Node.cloneNode does not copy over any properties that I add myself (code from original post):

    var theSource = document.getElementById("someDiv")
    theSource.dictator = "stalin";

    var theClone = theSource.cloneNode(true);
    alert(theClone.dictator); 

theClone does not contain any property "dictator".

I haven't been able to find any explanation for why this is the case. The documentation on MDN states that cloneNode "copies all of its attributes and their values", a line which is taken directly from the DOM specification itself.

This seems broken to me as it makes it next to impossible to do a deep copy of a DOM tree that contains custom properties.

Am I missing something here?

Community
  • 1
  • 1
Scott Cameron
  • 5,293
  • 2
  • 29
  • 32
  • I would probably just avoid using cloneNode, and if I want to clone something, I'd implement my own cloning function to clone the element how I see fit (for example, you could make a new one using the constructor, then copy attributes, copy properties, and possibly other custom stuff depending on your specific case). – trusktr Aug 21 '16 at 06:34

3 Answers3

8

A property is not equal to an attribute.

Use setAttribute() and getAttribute() instead.

var theSource = document.getElementById("someDiv")
theSource.setAttribute('dictator','stalin');

var theClone = theSource.cloneNode(true);
alert(theClone.getAttribute('dictator')); 
Dr.Molle
  • 116,463
  • 16
  • 195
  • 201
3

Not every property corresponds to an attribute. Adding a custom property to an element does not add an attribute, so what happens when you do that is not covered by the DOM spec.

In fact, what happens when you add a property to a host object (such as a DOM node) is completely unspecified and is by no means guaranteed to work, so I'd strongly recommend against doing it. Instead, I'd suggest using wrappers if you want to extend the functionality of host objects (as jQuery and many other libraries do).

Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • If you use wrappers, you'll need to make your own method to clone those wrappers when you want to copy that data. I think `cloneNode` should just be deprecated, as there are simply way too many use cases where it will just utterly fail. – trusktr Aug 21 '16 at 06:35
2

Tested this. cloneNode does include the custom attribute in the clone, but that attribute can't be retrieved directly. Try:

 var theSource = document.getElementById("someDiv")
 theSource.dictator = "stalin";
 //or better / more cross browser compatible
 theSource.setAttribute('dictator','stalin');

 var theClone = theSource.cloneNode(true);
 alert(theClone.getAttribute('dictator')); //so, use getAttribute 

It may be a browser problem with cloning expando properties. I ran a testcase (see later) from this rather old bugzilla report. It didn't work in Chrome and Firefox (both latest versions).

//code from testcase @ bugzilla
var a = document.createElement("div");      
a.order = 50;      
alert(a.order);      
b = a.cloneNode(true);      
alert(b.order);    
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • Then I suppose it may be browser dependent? In Chrome (latest) this works. – KooiInc Aug 07 '12 at 21:31
  • You have to create the attribute first using `createAttribute` first. https://developer.mozilla.org/en-US/docs/DOM/document.createAttribute. – marteljn Aug 07 '12 at 21:40