Javascript 闭包 - 全局范围内被覆盖函数的行为



这个问题更多的是关于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 = ...`'); }

如果在<script>标签中定义,它们会做同样的事情吗,对吧?

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

如果上面的问题没有意义,这里是改写;

  • 以下代码是否应该在任何 JS 运行时中执行相同的操作?
  • eval -ing 代码在上下文或全局范围内执行该特定代码?
  • 如何配置setTimeout调用,以便其"引号"之间的代码执行到调用该特定setTimeout的作用域内(请参阅下面的for中的第二次超时(?我的意思是,除了定义 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);
        }());
    }
    

关于一般行为的最初问题:

  • var done =function done基本上做同样的事情。它们将在内部作用域中隐藏外部定义,但不会在外部作用域中替换它。

  • 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 donedone 之间有区别,因为后者牵涉window.done,因此可以delete

语句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();