Why does cloneNode exclude custom properties?

2019-05-03 07:57发布

问题:

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?

回答1:

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')); 


回答2:

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).



回答3:

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);