场景
$.ajax({
url:'./apps/views/sb/fjmA_year/001/001/001_cfg.xml',
type:'get',
async:false,
success:function(result){
console.log($(result).clone()[0])
}
})
上图是一个请求xml文件的例子,我们一般会使用clone来复制该xml文档,这个用法在jq1.10以及以下的版本都不会出现问题。但是在jq1.11以上的版本这样使用时报错了。
Uncaught TypeError: Cannot read property 'ownerDocument' of null
at Function.Sizzle.contains (jquery.js:1468)
at Function.clone (jquery.js:5515)
at XMLDocument.<anonymous> (jquery.js:5843)
at jquery.js:141
at Function.map (jquery.js:503)
at jQuery.fn.init.map (jquery.js:140)
at jQuery.fn.init.clone (jquery.js:5842)
at Object.success (test.html?_ijt=50vdf9qihmv4rpsm7f34rgiaqi:70)
at fire (jquery.js:3148)
at Object.fireWith [as resolveWith] (jquery.js:3260)
阅读源码的clone方法发现1.11以上版本的clone方法和低版本的不同。
clone: function( elem, dataAndEvents, deepDataAndEvents ) {
var destElements, node, clone, i, srcElements,
inPage = jQuery.contains( elem.ownerDocument, elem );//此处调用了jquery.contains,该方法内部使用了elem.ownerDocument做判断。高版本直接使用$(result)调用clone方法是ownerDocument是null,所以传入contains的为null会报错。
if ( support.html5Clone || jQuery.isXMLDoc( elem ) ||
!rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
clone = elem.cloneNode( true );
// IE<=8 does not properly clone detached, unknown element nodes
} else {
fragmentDiv.innerHTML = elem.outerHTML;
fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
}
if ( ( !support.noCloneEvent || !support.noCloneChecked ) &&
( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) {
// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
destElements = getAll( clone );
srcElements = getAll( elem );
// Fix all IE cloning issues
for ( i = 0; ( node = srcElements[ i ] ) != null; ++i ) {
// Ensure that the destination node is not null; Fixes #9587
if ( destElements[ i ] ) {
fixCloneNodeIssues( node, destElements[ i ] );
}
}
}
// Copy the events from the original to the clone
if ( dataAndEvents ) {
if ( deepDataAndEvents ) {
srcElements = srcElements || getAll( elem );
destElements = destElements || getAll( clone );
for ( i = 0; ( node = srcElements[ i ] ) != null; i++ ) {
cloneCopyEvent( node, destElements[ i ] );
}
} else {
cloneCopyEvent( elem, clone );
}
}
// Preserve script evaluation history
destElements = getAll( clone, "script" );
if ( destElements.length > 0 ) {
setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
}
destElements = srcElements = node = null;
// Return the cloned set
return clone;
}
//这即为contains方法
Sizzle.contains = function( context, elem ) {
// Set document vars if needed
if ( ( context.ownerDocument || context ) !== document ) {
setDocument( context );
}
return contains( context, elem );
};
以上是1。11以上版本的实现,下面列出低版本的实现
clone: function( elem, dataAndEvents, deepDataAndEvents ) {
var srcElements,
destElements,
i,
clone;
if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
clone = elem.cloneNode( true );
// IE<=8 does not properly clone detached, unknown element nodes
} else {
fragmentDiv.innerHTML = elem.outerHTML;
fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
}
if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
// IE copies events bound via attachEvent when using cloneNode.
// Calling detachEvent on the clone will also remove the events
// from the original. In order to get around this, we use some
// proprietary methods to clear the events. Thanks to MooTools
// guys for this hotness.
cloneFixAttributes( elem, clone );
// Using Sizzle here is crazy slow, so we use getElementsByTagName instead
srcElements = getAll( elem );
destElements = getAll( clone );
// Weird iteration because IE will replace the length property
// with an element if you are cloning the body and one of the
// elements on the page has a name or id of "length"
for ( i = 0; srcElements[i]; ++i ) {
// Ensure that the destination node is not null; Fixes #9587
if ( destElements[i] ) {
cloneFixAttributes( srcElements[i], destElements[i] );
}
}
}
// Copy the events from the original to the clone
if ( dataAndEvents ) {
cloneCopyEvent( elem, clone );
if ( deepDataAndEvents ) {
srcElements = getAll( elem );
destElements = getAll( clone );
for ( i = 0; srcElements[i]; ++i ) {
cloneCopyEvent( srcElements[i], destElements[i] );
}
}
}
srcElements = destElements = null;
// Return the cloned set
return clone;
},
低版本的话不会用到ownerDocument属性故不会报错。
后来发现高版本时使用clone需要find到那个xml节点。使用find后它的ownerDocument属性就有值了
$.ajax({
url:'./apps/views/sb/fjmA_year/001/001/001_cfg.xml',
type:'get',
async:false,
success:function(result){
console.log($(result).find('XmlRWConfig').clone()[0])//高版本使用时
}
})
按如上方法解决了高版本clone报错的问题。