以前是玩c# winform的,感觉“函数”肯定总是不变的才对但今天遇到个奇怪的问题,有没有高手从原理方面解释一下:为什么刚赋值时两个变量指向同一函数,过了一会就不指向同一函数了原代码有点长,我已经尽量从实际环境中把没用的东西都去掉了点两下checkbox,预期结果是两次提示true,结果第2次提示false
<!DOCTYPE html>
<html>
<head><title></title></head>
<body>
<script>
    var game = {action: null};
    function setAction(b)
    {
        function doNothing()
        {
        }        if (b)
        {
            game.action = doNothing;
            alert(game.action == doNothing)
        }
        else
        {
            alert(game.action == doNothing);    //返回false,太奇怪了
            game.action = null;
        }
    }
</script>
<label for="chk">show time</label><input id="chk" type="checkbox" onchange="setAction(this.checked)"/>
</body>
</html>

解决方案 »

  1.   

    下面这样就是true了。var game = {action: null};
    function doNothing()
    {
    }
    function setAction(b)
    {
        if (b)
        {
            game.action = doNothing;
            alert(game.action == doNothing)
        }
        else
        {
            alert(game.action == doNothing);    //返回false,太奇怪了
            game.action = null;
        }
    }
      

  2.   

    这是因为,在JavaScript中,变量的作用域通常按函数划分,
    函数doNothing()定义在函数setAction()内部,其作用域也在setAction()内部,
    每当点击checkbox就会执行setAction(),而每当执行setAction(),
    就是重新定义一个doNothing()。这个doNothing()虽然与之前的函数名函数体都一样,
    但在内存中实际上是不同的。而game.action从第一点击checkbox开始,
    以后每次点击,game.action就一直指向第一次点击定义的doNothing。所以,1楼将doNothing()的定义放在函数setAction()的外部,
    这样,doNothing就不会被每次点击都重新定义了。
      

  3.   


    追问一下--- 照这样说,两个DoNothing函数的“实例”不同,我明白了。有没有办法识别它们是从同一处代码来的呢?比如利用prototype什么的... 有个保底的方法,转换成string比较函数体(除非有两个函数写的一样),有没有更直接的办法呢如果把DoNothing拿出来的话,函数容易重名,有很多麻烦。
      

  4.   


    var game = {action: null};
        function setAction(b){
            if(!setAction.doNothing){
                setAction.doNothing = function(){
                }
            }
     
            if (b){
                game.action = setAction.doNothing;
                alert(game.action == setAction.doNothing)
            }else{
                alert(game.action == setAction.doNothing);    //返回false,太奇怪了
                game.action = null;
            }
        }
      

  5.   

    大侠这是想要说明doNothing不一定要
    定义在setAction外部,内部也可以吗?
    的确是这样,您这个新的代码在函数
    setAction开头每次点击都会检查
    doNothing是否已经定义。
    避免了楼主原始代码中每次都会重新定义
    doNothing的做法。
    doNothing放在setAction内或外不是关键,
    避免doNothing重新定义才是关键。