将 Array.prototype.slice 方法应用于 querySelectorAll 的结果时出现奇怪的行为

发布于 2024-09-19 23:46:40 字数 1611 浏览 4 评论 0原文

我正在尝试使用 jQuery 的 Sizzle 选择器引擎作为自定义 Selenium 定位 API,如本文所示: http://johnjianfang.blogspot.com/2009/04/how-to-use-jquery-to-create-custom.html

不幸的是,当我使用 selenium.click('jquery=a.mylink'),没有任何反应。

selenium.click('css=a.mylink') 工作完美。

我做了一些研究,发现问题在于 jQuery 如何转换 querySelectorAll API 的结果。这是 jQuery 1.4.2 的片段:

Sizzle = function(query, context, extra, seed){
    context = context || document;

    // Only use querySelectorAll on non-XML documents
    // (ID selectors don't work in non-HTML documents)
    if ( !seed && context.nodeType === 9 && !isXML(context) ) {
        try {
            return makeArray( context.querySelectorAll(query), extra );
        } catch(e){}
    }

    return oldSizzle(query, context, extra, seed);
};


var makeArray = function(array, results) {
    array = Array.prototype.slice.call( array, 0 );

    if ( results ) {
        results.push.apply( results, array );
        return results;
    }

    return array;
};

当我像这样更改 makeArray 时:

var makeArray = function(arrayLikeObject, results) {

    var array = new Array(arrayLikeObject.length);
    for (var i = 0, n = arrayLikeObject.length; i < n; i++) {
        array[i] = arrayLikeObject[i];
    }

    if ( results ) {
        results.push.apply( results, array );
        return results;
    }

    return array;
};

它解决了这个奇怪的问题。

任何想法为什么这个修复有效?

I'am trying to use jQuery's Sizzle selector engine as a custom Selenium locate API, as in this article: http://johnjianfang.blogspot.com/2009/04/how-to-use-jquery-to-create-custom.html

Unfortunatly, when I use selenium.click('jquery=a.mylink'), nothing happens.

selenium.click('css=a.mylink') works perfectly.

I did a little research, and found that problem is in how jQuery converts the
result of the querySelectorAll API. Here is the snippet from jQuery 1.4.2:

Sizzle = function(query, context, extra, seed){
    context = context || document;

    // Only use querySelectorAll on non-XML documents
    // (ID selectors don't work in non-HTML documents)
    if ( !seed && context.nodeType === 9 && !isXML(context) ) {
        try {
            return makeArray( context.querySelectorAll(query), extra );
        } catch(e){}
    }

    return oldSizzle(query, context, extra, seed);
};


var makeArray = function(array, results) {
    array = Array.prototype.slice.call( array, 0 );

    if ( results ) {
        results.push.apply( results, array );
        return results;
    }

    return array;
};

When I change makeArray like this:

var makeArray = function(arrayLikeObject, results) {

    var array = new Array(arrayLikeObject.length);
    for (var i = 0, n = arrayLikeObject.length; i < n; i++) {
        array[i] = arrayLikeObject[i];
    }

    if ( results ) {
        results.push.apply( results, array );
        return results;
    }

    return array;
};

It solves this strange problem.

Any ideas why this fix works??!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最丧也最甜 2024-09-26 23:46:40

浏览器可能无法使用内置方法将 nodeList 转换为数组。您的后备方案几乎与 jQuery 1.4.2 源代码

// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
// Also verifies that the returned array holds DOM nodes
// (which is not the case in the Blackberry browser)
try {
    Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;

// Provide a fallback method if it does not work
} catch(e){
    makeArray = function(array, results) {
        var ret = results || [];

        if ( toString.call(array) === "[object Array]" ) {
            Array.prototype.push.apply( ret, array );
        } else {
            if ( typeof array.length === "number" ) {
                for ( var i = 0, l = array.length; i < l; i++ ) {
                    ret.push( array[i] );
                }
            } else {
                for ( var i = 0; array[i]; i++ ) {
                    ret.push( array[i] );
                }
            }
        }

        return ret;
    };
}

The browser may not be able to convert a nodeList to an array using built-in methods. Your fallback is almost exactly like the one included further down in the jQuery 1.4.2 source:

// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
// Also verifies that the returned array holds DOM nodes
// (which is not the case in the Blackberry browser)
try {
    Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;

// Provide a fallback method if it does not work
} catch(e){
    makeArray = function(array, results) {
        var ret = results || [];

        if ( toString.call(array) === "[object Array]" ) {
            Array.prototype.push.apply( ret, array );
        } else {
            if ( typeof array.length === "number" ) {
                for ( var i = 0, l = array.length; i < l; i++ ) {
                    ret.push( array[i] );
                }
            } else {
                for ( var i = 0; array[i]; i++ ) {
                    ret.push( array[i] );
                }
            }
        }

        return ret;
    };
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文