3

我是前端编程的新手。当我学习 jQuery 时,我遇到了这个问题。这是我的代码:

<script type="text/javascript">
$(document).ready(function(){
  var msg ="hi";
  $("#test1").click(function(){alert(msg)});
  msg ="hello";
  $("#test2").click(function(){alert(msg)});
});
</script>
</head>
<body>
  
<button id="test1">test1</button>
<button id="test2">test2</button>

运行此代码时,两个警报都会打印“hello”。我除了点击的第一个按钮应该用“hi”提醒。为什么它会这样?这是正确的行为吗?是因为范围限制吗?

4

5 回答 5

5

您遇到了范围界定问题。

当您到达实际单击的代码点时 msg === "hello"

于 2012-09-20T18:54:28.593 回答
2

msg执行处理程序代码时的值为“hello”。

或者,您可以将其作为数据传递给处理函数访问它..

$(document).ready(function(){
  var msg ="hi";
  $("#test1").click({msg: msg}, function(e){alert(e.data.msg)});
  msg ="hello";
  $("#test2").click({msg: msg}, function(e){alert(e.data.msg)});
});

演示:http: //jsfiddle.net/h36pf/

于 2012-09-20T19:25:23.893 回答
1

在准备好文档时,您的 javascript 代码将被执行。此时,click 函数绑定到两个按钮,并msg首先设置为 hi,然后执行下一行并msg用 hello 覆盖。
在触发点击时msg已经被覆盖,因此输出你好。

这是正确和预期的行为。您可以通过使用两个变量或在点击时设置它们(在点击函数中)来克服这个问题。

于 2012-09-20T18:56:31.353 回答
1

这里有很多大部分正确的解释,但令我惊讶的是,没有人在这里抛出关键概念:闭包。

基本上发生的事情是当你声明你的两个函数时,它们声明的范围形成了一个闭包。这意味着该闭包内的变量对函数仍然可用。换句话说:

$(document).ready(function(){
    // this begins a closure
    var msg ="hi";
    // you are simply declaring a function here, not calling it
    $("#test1").click(function(){alert(msg)});
    msg ="hello";
    // ditto
    $("#test2").click(function(){alert(msg)});
    // the end of the closure...msg has the value "hello"
});

然后过了一段时间,点击事件被调用。附加到点击事件的函数仍然可以访问闭包(其中的值为msg“hello”)。

在闭包中“捕获”变量值的传统方法是创建一个“立即调用函数表达式”(IIFE)。基本上,您可以将其视为创建一个包含变量立即值的全新闭包。您可以像这样重新编写代码以使用 IIFE:

$(document).ready(function(){
    // this begins a closure
    var msg ="hi";
    // the following creates an anonymous function with a single parameter
    // AND invokes it immediately, creating another closure in which the
    // value of msg1 is "hi".
    (function(msg1){
        $("#test1").click(function(){alert(msg1)});
    })(msg);
    msg ="hello";
    // ditto
    (function(msg2){
        $("#test2").click(function(){alert(msg2)});
    })(msg);
});

我希望这能让你更清楚地了解正在发生的事情,以及如何获得你想要的东西。

于 2012-09-20T19:15:02.493 回答
0

这是预期的行为。这通常是不直观的,但这就是 javascript 的工作原理。获得预期结果的最简单方法是使用如下函数:

$(document).ready(function(){
  var msg ="hi";
  $("#test1").click(getCallback(msg));
  msg ="hello";
  $("#test2").click(getCallback(msg));
});

function getCallback(msg){
    return function(){
        alert(msg);
    }
}

内的msg参数对于每个调用getCallback都有一个单独的msg变量,它将为每个单独的调用维护正确的值。

于 2012-09-20T19:00:45.940 回答