Javascript闭包 - 来自全局范围的重写函数的行为

时间:2012-02-18 03:44:18

标签: 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 = ...`'); }

如果在<script>标签内定义,它们是否都会做同样的事情,对吗?

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

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

  • 以下代码应该在任何JS运行时执行相同的操作?
  • eval - 代码在任何地方执行上下文或全局范围内的特定代码?
  • 如何配置setTimeout调用,以便其“引号”之间的代码执行到调用特定setTimeout的范围内(请参阅{{}内的第二个超时1}}下面)?我的意思是除了定义window.blabla函数并告诉他们在运行后删除自己还有其他方法吗?

    for

3 个答案:

答案 0 :(得分:1)

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

  • var done =function done基本相同。它们会影响内部范围中的外部定义,但它们不会在外部范围内替换它。

  • done =将在范围内设置相应的done变量,或者如果此变量不存在且程序未在严格模式下运行,则会创建全局变量。

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

至于非常邪恶的setTimeout和eval问题:

  • 是的,我想这种东西应该足够标准化,以便在任何地方都能正常工作。无论如何我仍然会测试它。 (或者你可以使用不同的解决方案,考虑到邪恶的评估是多少)

  • eval 在当前范围内运行代码(使用深黑魔法来执行此操作)。如果要在全局范围内运行代码,可以使用new Function代替。

  • 为了让settimeout在curent范围内运行字符串,您可以自己添加 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
    }());
    
  • 再一次,你为什么要在setTimeouts中评估一些东西?这听起来非常邪恶!

答案 1 :(得分:0)

var donedone之间存在差异,因为后者暗示window.done,因此可能delete

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

答案 2 :(得分:0)

关于第一个区块的一个注释。当您为函数指定第一行中的名称时,该函数名称将在编译时进行解析,并在作用域内的任何位置可用。如果您只是将函数分配给变量,那么该函数(即变量)仅在运行时 定义后可用,甚至如果您给它命名。< / p>

例如:

// 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();