Javascript闭包-全局范围内被重写函数的行为

Javascript闭包-全局范围内被重写函数的行为,javascript,scope,closures,Javascript,Scope,Closures,这个问题更多的是关于javascript原则的 function done(){ console.log('done defined with `function done(){ ...`'); } var done = function(){ console.log('done defined with `var done = ...`'); } done = function(){ console.log('without `var`, just `done = ...`'); } 如果在

这个问题更多的是关于javascript原则的

function done(){ console.log('done defined with `function done(){ ...`'); }
var done = function(){ console.log('done defined with `var done = ...`'); }
done = function(){ console.log('without `var`, just `done = ...`'); }
如果在
标记中正确定义,它们会做相同的事情吗

但是如果我将它们放在一个闭包
(function(){
函数定义在这里
}())
这三种类型中的任何一种会覆盖全局定义的函数done()或在各自闭包中定义的任何其他done()函数吗

如果上面的问题没有意义,这里是重新措辞

  • 下面的代码在任何JS运行时都应该做同样的事情吗
  • eval
    -ing code anywhere在上下文或全局范围内执行特定代码
  • 如何配置
    setTimeout
    调用,以使其“引号”之间的代码在调用该特定
    setTimeout
    的范围内执行(请参见下面的
    中的第二个超时)?我的意思是,除了定义window.blabla函数并告诉它们在运行后删除自己之外,还有其他方法吗

    function done(d){ console.log('cha cha cha: '+d); }
    setTimeout( function(){ done(2); }, 3500 );
    
    for(i=0; i<10; i++){
        (function(){
            done = function(x){ console.log('done #'+i+' sais: '+x); }
            setTimeout(function(){ done(i*2); },2500);
            setTimeout(function(){ done(i*2); }.toString()+'(); ',2500);
        }());
    }
    
    函数完成(d){console.log('chacha:'+d);}
    setTimeout(函数(){done(2);},3500);
    
    对于(i=0;i关于一般行为的初始问题:

    • var-done=
      function-done
      do基本上是一样的。它们将在内部范围中隐藏外部定义,但不会在外部范围中替换它

    • done=
      将在作用域中设置相应的
      done
      变量,或者如果该变量不存在且程序未在严格模式下运行,则将创建一个全局变量

    • 在全局级别上,在任何函数之外,
      var-done=
      done=
      应该工作相同,但是如果您尝试在另一个脚本标记中使用变量,它们在IE中的工作方式就不同了(坚持使用
      var=
      ,无论如何都会更好)

    关于非常邪恶的设置超时和评估问题:

    • 是的,我想这类东西应该足够标准化,以便在任何地方都能使用相同的东西。我仍然会测试它。(或者你可以使用不同的解决方案,考虑到eval是多么邪恶)

    • eval在当前作用域中运行代码(使用deep black magic)。如果要在全局作用域中运行代码,可以使用
      new Function

    • 为了让settimeout在当前作用域中运行字符串,您可以自己添加eval:

      var done = function(d){ console.log('outer done', d); };
      
      (function(){
          var done = function(x){ console.log('inner done', x); };
      
          setTimeout(function(){ done(1); }, 200);           //inner done
          setTimeout('done(2)', 400);                        //outer done
          setTimeout(function(){ eval('done(3)'); }, 600);   //inner done
      }());
      
    • 再说一次,你为什么要在设定的超时时间里评估事情?这听起来非常邪恶


    var done
    done
    之间存在差异,因为后者涉及
    window.done
    ,因此可以
    delete
    d

    语句
    done=foobar;
    将覆盖作用域链中的下一个“done”变量。如果存在一个局部变量
    var
    ,它将更改,如果存在全局变量,它将覆盖该变量,如果没有,它将创建一个新的全局变量。
    所有这些都不会影响其他作用域(闭包)中的任何私有变量。

    第一个块上有一个注释。当您在第一行中为一个函数命名时,该函数名在编译时被解析,并且在作用域内的任何位置都可用。如果您只需将一个函数赋给一个变量,那么该函数(即变量)仅在运行时定义后才可用,甚至如果您给它命名

    例如:

    // this is valid
    foo();
    function foo(){ console.log("foo"); }
    
    // this throws an error...
    bar();
    var bar = function (){ console.log("bar"); };
    
    // ...and so does this...
    baz();
    var bat = function baz(){ console.log("bazbat"); };
    
    // ...and this!
    baz();
    

    不要使用第二个超时方法。或者有什么原因吗?最完整的答案,谢谢。这不是坏事,尽管我用悍马穿越一只猴子,告诉猴子从悍马内部做一些事情,为了让我所有的代码都在同一个JS项目中,我不得不做一些疯狂的事情,比如通过JSON传递函数。这也是一个错误语法突出显示的问题。好吧,我住的地方,一只猴子和一辆悍马的交叉被认为是最邪恶的:p对于带有eval的setTimeout,你不需要eval,你只需要将eval中的函数绑定到这个范围就可以了。@helly0d:我知道,这就是我在第一个例子中所做的。setTimeout中的eval是c与向settimeout传递字符串的大小写兼容。