jquery的1.11以上版本clone方法报错

场景

$.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报错的问题。

猜你喜欢

转载自blog.csdn.net/qq_33203555/article/details/81159315