Javascript 执行上下文和闭包-特定代码的问题

Javascript 执行上下文和闭包-特定代码的问题,javascript,closures,Javascript,Closures,在这里,第17行和第18行的执行上下文是分开的,但将创建的闭包将引用“语言”的同一实例,因为函数在第15行返回,并且闭包中具有相同的“语言”。现在,由于第16行中函数“test”的初始化不同,第18行将具有不同的执行上下文以及不同的语言实例。因此,输出将是 1. function test(language){ 2. return function(set){ 3. if(set) 4. { 5. language=set; 6.

在这里,第17行和第18行的执行上下文是分开的,但将创建的闭包将引用“语言”的同一实例,因为函数在第15行返回,并且闭包中具有相同的“语言”。现在,由于第16行中函数“test”的初始化不同,第18行将具有不同的执行上下文以及不同的语言实例。因此,输出将是

 1. function  test(language){
 2.   return function(set){
 3.       if(set)
 4.           {
 5.       language=set;
 6.       console.log("Changed "+language);
 7.           }
 8.       else
 9.           {
 10.               console.log(language);
 11.           }
 12.   }
 13. }
 14.
 15. var a=test("en");
 16. var b=test("es");
 17. a("Spanish");
 18. a();
 19. b();
但是现在,

Changed Spanish
Spanish
es
这里,第17行和第18行将具有不同的执行上下文,但具有相同的“语言”实例。但是“a”和“b”变量的闭包将有不同的“language”实例,就像前面的示例一样,即使值被“a”更改为“西班牙语”,调用“b”时显示的值仍然是“es”,因为b的“language”与a的“language”不同。但在这里,当我在第17行中将a的语言更改为“西班牙语”时,我检查了输出,b的“语言”也更改了,给出了如下输出:

 1. function  test(){ language = "English"
 2.   return function(set){
 3.       if(set)
 4.           {
 5.       language=set;
 6.       console.log("Changed "+language);
 7.           }
 8.       else
 9.           {
 10.               console.log(language);
 11.           }
 12.   }
 13. }
 14.
 15. var a=test();
 16. var b=test();
 17. a("Spanish");
 18. a();
 19. b();
Changed Spanish
Spanish
Spanish
 1. function  test(){ var language = "English"
 2.   return function(set){
 3.       if(set)
 4.           {
 5.       language=set;
 6.       console.log("Changed "+language);
 7.           }
 8.       else
 9.           {
 10.               console.log(language);
 11.           }
 12.   }
 13. }
 14.
 15. var a=test();
 16. var b=test();
 17. a("Spanish");
 18. a();
 19. b();
 20. console.log(this.language)
现在,理解第一行和第二行是因为与第一个示例一样,所有“a”函数调用中都存在相同的“language”实例,但b的闭包必须具有不同的language实例。那么为什么输出不如下所示:

 1. function  test(){ language = "English"
 2.   return function(set){
 3.       if(set)
 4.           {
 5.       language=set;
 6.       console.log("Changed "+language);
 7.           }
 8.       else
 9.           {
 10.               console.log(language);
 11.           }
 12.   }
 13. }
 14.
 15. var a=test();
 16. var b=test();
 17. a("Spanish");
 18. a();
 19. b();
Changed Spanish
Spanish
Spanish
 1. function  test(){ var language = "English"
 2.   return function(set){
 3.       if(set)
 4.           {
 5.       language=set;
 6.       console.log("Changed "+language);
 7.           }
 8.       else
 9.           {
 10.               console.log(language);
 11.           }
 12.   }
 13. }
 14.
 15. var a=test();
 16. var b=test();
 17. a("Spanish");
 18. a();
 19. b();
 20. console.log(this.language)

答案在于,在第二个代码片段的第1行中声明变量时不使用关键字
var
。正如在其他资源中发现的那样,如果我们按原样声明变量,那么它将在全局上下文中声明

更改代码如下:

Changed Spanish
Spanish
English
我在代码中添加了额外的第20行,以证明该变量不在窗口范围内,因此上述代码段的输出如下所示:

 1. function  test(){ language = "English"
 2.   return function(set){
 3.       if(set)
 4.           {
 5.       language=set;
 6.       console.log("Changed "+language);
 7.           }
 8.       else
 9.           {
 10.               console.log(language);
 11.           }
 12.   }
 13. }
 14.
 15. var a=test();
 16. var b=test();
 17. a("Spanish");
 18. a();
 19. b();
Changed Spanish
Spanish
Spanish
 1. function  test(){ var language = "English"
 2.   return function(set){
 3.       if(set)
 4.           {
 5.       language=set;
 6.       console.log("Changed "+language);
 7.           }
 8.       else
 9.           {
 10.               console.log(language);
 11.           }
 12.   }
 13. }
 14.
 15. var a=test();
 16. var b=test();
 17. a("Spanish");
 18. a();
 19. b();
 20. console.log(this.language)

在问题的第二个代码片段中,“language”变量出现在全局范围内,因此它将返回“西班牙语”,而不是未定义。

省略
var
let
const
,导致2020年仍然出现错误。使用
let language=“English”
,并转到严格模式,在该模式下,这将抛出并使您立即注意到问题。是的,@ASDFGerte。我在回答中补充了同样的问题,并作了更多解释。请检查一下。