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

3
我正在尝试使用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;
};

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

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


arrayA[0] === arrayB[0] 怎么样? - palswim
对于arrayA[0]中的每个属性p,如果arrayA[0][p]不等于arrayB[0][p],那么就会弹出“diff”的提示框。但是这段代码从来没有弹出过提示框 :) 注:true表示真,even表示偶数。 - Vadim P.
你在哪些浏览器中测试过这个? - Andy E
你修复了jQuery。恭喜你。 - Anonymous
1个回答

1

浏览器可能无法使用内置方法将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;
    };
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接