简体   繁体   English

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

[英]Javascript closures - behavior of overridden functions from the global scope

This question is more on javascript principle. 这个问题更多的是关于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 = ...`'); }

If defined right inside <script> tags, will they all do the same thing, right? 如果在<script>标记内定义它们,它们是否都会做相同的事情,对吗?

But if I place them in a closure (function(){ function definintion goes here }()) will any of these three types override either the globally defined function done() or any other done() functions that are defined inside their respective closures? 但是,如果我将它们放在闭包中(function(){ 函数定义在此处 }()) ,这三种类型中的任何一种都会覆盖全局定义的函数done()或在其各自闭包中定义的任何其他done()函数?

If the question above doesn't make sense, here's to rephrasing; 如果上述问题没有道理,请改写;

  • is the following code supposed to do the same thing in any JS runtime? 以下代码在任何JS运行时中都应该做相同的事情吗?
  • eval -ing code anywhere executes that particular code within the context or the global scope? eval代码可以在上下文或全局范围内的任何地方执行该特定代码吗?
  • how can a setTimeout call be configured so that the code between its "quotes" executes to inside the scope where that particular setTimeout has been called (please see second timeout inside for below)? 如何才能setTimeout呼叫进行配置,以便其“引号”之间的代码执行中具有特定范围内setTimeout被称为(请参阅第二超时里面for下面)? I mean is there any other way besides defining window.blabla functions and telling them to delete themselves after they run? 我的意思是除了定义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); }()); } 

For the initial question on general behaviour: 对于有关一般行为的最初问题:

  • var done = and function done do basicaly the same thing. var done =function done执行相同的操作。 They will shadow the outer definition in the inner scope but they will not replace it on the outer scope. 它们将在内部作用域中隐藏外部定义,但不会在外部作用域中替换它。

  • done = will set the corresponding done variable in scope or will create a global variable if such a variable does not exist and the program is not running in strict mode. done =将在范围内设置相应的done变量,或者如果不存在这样的变量并且程序不在严格模式下运行,则将创建一个全局变量。

  • At a global level, outside any function, var done = and done = should work the same, but they work differently in IE if you try to use the variable in another script tag (stick to var = - its better anyway). 在全局级别上,在任何函数之外, var done =done =应该工作相同,但是如果您尝试在另一个脚本标签中使用变量,则它们在IE中的工作方式有所不同(始终坚持使用var = -更好)。

As for the very evil setTimeout and eval questions: 至于非常邪恶的setTimeout和eval问题:

  • Yes, I guess this kind of stuff should be standardized enough to work the same everywhere. 是的,我想这种东西应该足够标准化,以便在任何地方都可以使用。 I would still test it anyway. 无论如何,我仍然会对其进行测试。 (Or you could use a different solution, given how evil eval is) (或者,考虑到恶性评估,您可以使用其他解决方案)

  • eval runs code in the current scope (using deep black magic to do so). eval在当前范围内运行代码(使用深黑魔术来运行)。 If you want to run code on the global scope you can use new Function instead. 如果要在全局范围内运行代码,则可以改用new Function

  • In order to have the settimeout run the string in the curent scope you can add the eval yourself: 为了让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 }()); 
  • Once again, why are you eval-ing things in the setTimeouts? 再一次,为什么要评估setTimeouts中的内容? This all sounds profoundly evil! 这听起来完全是邪恶的!

There are differences between var done and done , because the latter implicates window.done and can be delete d therefore. var donedone之间有区别,因为后者涉及window.done ,因此可以delete d。

The statement done = foobar; 语句done = foobar; will overwrite the next "done" variable in the scope chain. 将覆盖作用域链中的下一个“完成”变量。 If there is a local var , it changes that, if there is a global one, it will overwrite that one, anf if not it will create a new global one. 如果有一个本地var ,它将更改为,如果有一个全局var ,它将覆盖该var ;如果没有,它将创建一个新的全局var All these will not affect any private variables in other scopes (closures). 所有这些都不会影响其他作用域(闭包)中的任何私有变量。

One note on your first block. 在第一块上的一个音符。 When you give a function a name as you have in the first line, that function name is parsed at compile time and available anywhere within the scope. 当您像在第一行中一样给函数命名时,该函数名称将在编译时进行解析,并且可以在范围内的任何位置使用。 If you simply assign a function to a variable, then that function (ie, variable) is only available at runtime after the definition, even if you give it a name. 如果仅将函数分配给变量,则该函数(即变量)仅在定义之后在运行时可用, 即使您给它起了名字。

For example: 例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM