Javascript变量范围问题

时间:2010-09-17 18:56:34

标签: javascript jquery variables scope

我在使用javascript解决范围问题时遇到问题。 我有一个数组,dog []是从JSON定义的,我需要从嵌套函数内部访问。

function blah(json) {
 for (var u = 0; u < json[0][1][u].length; u ++ ) {
    var dog = 'k' + json[0][1][u].doggies;
    console.log(dog); // prints array of doggie strings
    $('#puppy').click(function(dog) {    // dog is passed in the function
       console.log(dog); // Syntax error, unrecognized expression: #[object Object]
       $('#' + dog).css('display, 'none');
     });
   }
 }

当我不将狗传入点击功能时:我得到:

 $('#puppy').click(function() {
  console.log(dog) // (12)  main.js:122k4c812e3a7275e10331000000 - this is the last value in the array - from safari console
  $('#' dog).css('display', 'none);
   }

有没有人有任何建议让每个元素都传递给click函数? 或者我是否错误地调用css方法来隐藏这些div?

4 个答案:

答案 0 :(得分:4)

问题1

Closures绑定整个函数的作用域,而不是单个变量或值。

以此代码为例:

function foo() {
    var i, func;

    for (i = 0; i < 10; ++i) {
        if (i == 0) {
            func = function () {
                alert(i);
            }
        }
    }

    func();
}

foo();

您可能希望foo导致0收到提醒。但是,自创建分配给i的函数以来,func的值已更改;拨打func提醒“10”。

这是另一个说明这个概念的例子:

function foo() {
    var i = 42;

    function func() {
        alert(i);
    }

    for (i = 0; i < 10; ++i) {
        // do nothing
    }

    func();
}

foo();

尝试弄清楚会发出什么警报,并将代码作为测试运行。

问题2

第二个问题是变量是在函数范围内绑定的(而不是你期望的块范围)。

拿这段代码:

function foo() {
    var i;

    for (i = 0; i < 10; ++i) {
        var j = i;
    }

    alert(j);
}

foo();

您可能希望此代码警告“未定义”,抛出运行时错误,甚至抛出语法错误。但是,“10”会被警告。为什么?在JavaScript中,上述代码被有效地翻译成:

function foo() {
    var i;

    var j;

    for (i = 0; i < 10; ++i) {
        j = i;
    }

    alert(j);
}

foo();

从这个例子中可以更清楚地看到“10”确实被警告了。

解决方案

那么你如何解决问题呢?最简单的方法是改变你的逻辑:不是每只狗附加一个事件处理程序,每个狗集合攻击一个事件处理程序。例如:

function blah(json) {
    $('#puppy').click(function () {
        var u, dog;

        for (u = 0; u < json[0][1][u].length; u++) {
            dog = 'k' + json[0][1][u].doggies;

            console.log(dog);

            $('#' + dog).css('display', 'none');
        }
    });
}

如果您对现有代码的“正确”转换感兴趣(即具有相同的行为,除了修复了错误),我也可以举例说明。但是,我上面给出的解决方案是一个更好的解决方案,可以使代码更清晰。

答案 1 :(得分:2)

重要提示:

您忘了关闭报价。这样:

$('#' + dog).css('display, 'none');

应该是:

$('#' + dog).css('display', 'none');

改进的循环:

您的脚本存在一些问题。我将专注于循环的整体逻辑结构。

不要将许多处理程序附加到.click(),而是使用jQuery的 .each() 附加一个迭代JSON的处理程序。 .each()回调的第一个参数是索引号,第二个参数是值。您可以通过命名参数或使用arguments[0]arguments[1]来使用这些参数。我展示了以下的方法:

为了演示目的,我添加了一些测试输出:

function blah(json) {
     $('#puppy').click(function() { 

          // iterate over each json[0][1]
        $.each(json[0][1], function(index, value) {

              // Your original 2 lines
            console.log(value);
            $('#' + value).css('display', 'none');

              // This is just test output, so you can see what is going
              // on.
            $("body").append("Number " + index + " is " + value ".<br/>");
        });
     });
}     

答案 2 :(得分:1)

为什么不给小狗一个班级.dog并在点击#puppy时隐藏它们?

$("#puppy").click(function() {
    $(".dog").hide();
});

或者因为你的狗的ID似乎以k开头,你可能会考虑这样的事情:

$("#puppy").click(function() {

    // hide everything with ID beginning with 'k'
    $('[id^=k]').hide();
});

答案 3 :(得分:0)

你不能像在那里那样将dog值传递给jquery click事件。点击功能签名是:

$(object).click(function(){


});

你不能像这样经过狗。即使函数期望参数,命名它也会导致问题。您可能需要将dog的值存储在更全局的范围内,以便在单击事件发生时,您仍然可以访问它。