范围和关闭附录—注释

这是我关于附录A:动态范围,附录B:填充块范围和附录C:词汇的注释,这是Kyle Simpson的《 您不知道Javascript:范围和闭包》一书的内容

将词汇范围与动态范围进行比较可以更好地帮助我们理解词汇范围。 请记住, JavaScript具有词法范围

词法作用域是写时,而动态作用域是运行时。 词法作用域关心在何处声明函数,而动态作用域关心在何处调用函数。

这是JavaScript中的作用词范围:

 函数foo(){ 
console.log(a); // 2
}
功能bar(){
var a = 3;
foo();
}
var a = 2; bar();

由于词汇范围中的查找规则, bar()在全局范围中打印a的2值。 foo()首先在foo()的范围内检查变量,然后检查解析查询的全局范围。

JavaScript中的理论动态范围如下所示:

 函数foo(){ 
console.log(a); // 3(不是2!)
}
功能bar(){
var a = 3;
foo();
}
var a = 2; bar();

打印3是因为从bar()调用了foo() ,它在bar()`范围内检查变量,并找到值为3a变量。

再次注意,这是一个理论插图,可帮助我们理解词汇范围。 JavaScript具有词法范围!

附带说明, this与动态范围有关,因为它关心如何调用函数。

可以使用try catch语句在ES6之前的环境中polyfill块作用域。 块范围存在于catch子句中。

这是ES6块范围:

  { 
令a = 2;
console.log(a); // 2
}
console.log(a); //参考错误

这是一个try catch polyfill:

 尝试{掷2} {抓住一个} { 
console.log(a); // 2
}
console.log(a); // ReferenceError

Google有一个名为Traceur的项目,该项目将ES6功能转换为ES6之前的环境,其功能类似于上述代码。

为了使代码块更具可读性,Simpson建议使用以下两种方法之一明确地编写代码块:

1)在代码前加上注释:

  / *让* / {让a = 2 
console.log(a);
}
console.log(a); // ReferenceError

2)像这样的可读不支持的语法,该语法通过Simpson的let-er工具进行了编译:

 让(a = 2){ 
console.log(a); // 2
}
console.log(a); // ReferenceError

对于代码块的编译,try / catch是比IIFE更好的解决方案,因为IIFEs属性作为一个函数可以更改this的含义, returnbreakcontinue 。 此类更改可能会产生不良结果。

如果要在代码中包括块作用域,则可以使用上述工具。

我认为,当读者对词法范围和this有更好的理解时,将附录C更好地放在下一本有关this标识符的YDKJS书籍中。 我将在下面给出一个简短的摘要,并在完成YDKJS之后重新访问该附录:this和Object prototypes

ES6中引入的箭头功能(表示为=> )在其内部功能方面有不同的行为。

如果将setTimeout (或在运行时似乎经过任何时间)与使用this的对象方法一起使用,则它将失去与使用this对象的对象的绑定。

如果在对象定义的箭头函数中引用this函数,则它将遵循词汇作用域规则而不是this绑定规则。 辛普森说,这是一种变通方法,可以解决在代码中无法理解和正确利用this问题。 我们必须在对象定义中使用bind()来适当地利用this

这表明胖箭头函数的作用不仅仅是使函数声明更短(在这种情况下,它们以不良的做法编码为JavaScript)。