Javascript:递归,jQuery错误

Javascript:递归,jQuery错误,javascript,jquery,recursion,Javascript,Jquery,Recursion,使用jQuery处理导航菜单脚本。脚本采用递归设计,因此菜单的级别数没有硬编码限制 我将从代码开始: navigationMenu.prototype.reset = function ( ulElement, colorIndex, colors ) { //Color index should always be 1 when directly calling this function var listItems = $(ulElement.children); var numItems

使用jQuery处理导航菜单脚本。脚本采用递归设计,因此菜单的级别数没有硬编码限制

我将从代码开始:

navigationMenu.prototype.reset = function ( ulElement, colorIndex, colors ) { //Color index should always be 1 when directly calling this function
var listItems = $(ulElement.children);
var numItems = listItems.length;
var targetWidth = (100 / numItems) + '%';

listItems.each( function ( x ) {
    var children = $(listItems[x].children);
    var xT = $(listItems[x]).prop('tagName');
    var subMenu = null;

    children.each( function ( y ) {
        var yT = $(children[y]).prop('tagName'); 

        if (yT == 'UL') {
            subMenu = $(children[y]);
        } else if (yT == 'A') {
            $(children[y]).css('background-color', colors[colorIndex-1]); //Offset by 1 to facilitate for 0 indexed arrays
            $(children[y]).hover( function () { //Set hover color to the opposite
               $(children[y]).css('background-color',colors[(3-colorIndex)-1]); //3-1 = 2 and 3-2 = 1, subtract 1 to facilitate 0 indexed arrays
            }, function() {
                $(children[y]).css('background-color',colors[colorIndex-1]); //3-1 = 2 and 3-2 = 1, subtract 1 to facilitate 0 indexed arrays
            }); //Rest of style SHOULD be handled by css (width 100%, text color, text align)
        }
    });

    if (subMenu !== null) { //Recurse
        navigationMenu.prototype.reset(subMenu, (3 - colorIndex), colors); //Not defined?
    }

    if (xT == 'LI') { //Format the element
        $(listItems[x]).css('width',targetWidth);
        $(listItems[x]).css('background-color', colors[colorIndex]);
    }
});
};
接下来是错误:

Uncaught TypeError: Cannot read property 'firstChild' of null <-whitespace-> jquery-1.11.1.min.js:2
这是前一个错误遗留下来的,我很难让它识别递归函数调用。我在这里尝试了以下几行,但它们不允许函数继续进行:

this.reset(subMenu, (3 - colorIndex), colors);
reset(subMenu, (3 - colorIndex), colors);
navigationMenu.reset(subMenu, (3 - colorIndex), colors);
此外,在文档准备就绪时调用此函数:

$(document).ready(function() {
    s = new navigationMenu('#NavMenu', '#884106', '#000000', -1);
});

编辑:修改代码,使用x/y代替索引,使用xT/yT代替标记(删除了同名的嵌套变量)

当您第一次调用
导航菜单.prototype.reset
时,我猜
ulement
是一个DOM元素,但当您递归调用它时,您传递的是
子菜单,它是一个jQuery对象。这将是以下行的一个问题:

var listItems = $(ulElement.children);
尝试更改以下代码行:

navigationMenu.prototype.reset(subMenu, (3 - colorIndex), colors);
致:


我更喜欢总是在引用jQuery对象的变量前面加上“$”以保持它们的直线性

您还可以在指定给
.each()
的函数中使用
。因此,不是:

children.each(function(index) {
    var tag = $(children[index]).prop('tagName');
你可以:

children.each(function() {
    var $child = $(this),
        tag = $child.prop('tagName'); 

您还可以考虑使用jQuery <代码>子()/代码>方法,而不是<代码>子< /代码> DOM元素属性

避免在所有情况下使用嵌套变量变量的相同名称使用索引两次感到奇怪。我也觉得为同一个想法使用不同的名称很奇怪。但是你应该使用
this
而不是
listItems[index]
children[index]
我不想说你的错或争论@A.Wolff,但我觉得这是一种风格选择。测试表明,处理时间/效率没有差别,使用它并不能解决问题。有一件事肯定是个问题,那就是行
navigationMenu.prototype.reset.call(我,子菜单,(3-颜色索引),颜色)在menu.js中。使用
导航菜单调用
重置
函数。原型
。您需要将var me=作为
reset()
中的第一条语句执行,并将该行更改为
me.reset(子菜单(3-colorIndex),colors)
。这并不能解决问题,但肯定是错误的。有趣的反馈,您的区别是完全正确的,将第一次出现的问题更改为jQuery select会立即导致问题,而不是等待第二次出现。至于关于“this”的评论,我不喜欢这种方法,我的测试表明两者之间没有性能差异。这就是为什么我问你们。你的修理工作做得很好。谢谢
children.each(function(index) {
    var tag = $(children[index]).prop('tagName');
children.each(function() {
    var $child = $(this),
        tag = $child.prop('tagName');