以下是问题:
究竟什么是封闭的背景?这是进一步复杂的,因为ES6允许{}成为块/范围/上下文。 {}作为分隔符足以定义一个"封闭的上下文"或者必须在功能范围内。
一个具体的例子:
let EventEmitter = require('events').EventEmitter;
class Person extends EventEmitter {
constructor(name) {
super();
this.name = name;
}
}
let mary = new Person('mary');
mary.on('speak', (said) => {
console.log(
${this.name}: ${said}
);
});
mary.emit('speak', 'you may delay, but time will not');
它只是设置自定义事件,并在触发自定义事件时添加回调函数。为什么这里的箭头功能不起作用?
"玛丽"是调用" on"的对象。功能,应该设置"这个"在" on"玛丽"。最重要的是,箭头功能在" on"中定义。函数在其参数位置(在词法上足够,对吗?),为什么箭头函数不能得到"这个"来自"封闭上下文"的价值,即" on"功能在这里???
使用传统函数定义的相同示例:
${this.name}: ${said}
现在它有效。我理解,鉴于旧的函数定义方式,console.log(this)现在可以动态绑定到调用它的对象。但等等," mary"是对象和" on"是被调用的直接函数。不应该" on"为其中的匿名函数形成一个闭包?我记得"这个"在嵌套函数内无法访问"这个"它的封闭(封闭的背景,再次,呵呵),因此不应该得到" mary" refernce。为什么它在这里有用?
当我们在函数中讨论某事(比如说A)时,它是否意味着A必须在函数的{}中,或者A也可以在参数/参数区域中?也就是说,function(){A} vs. function(A){}。
类似地,如果箭头函数作为函数(()=>()){}之类的参数传递,外部函数是否考虑其封闭范围?或者这种情况下的封闭范围是外部函数的外部?
以上可能听起来很愚蠢。非常感谢你的帮助。
答案 0 :(得分:2)
我可能不会在这里精确地使用“范围”一词,但基本上只是将范围视为变量名称的映射,以及它们所指向的内存中的位置;嵌套范围的名称/变量对阴影(覆盖)在封闭(又称父级)范围内具有相同名称的关联。
function foo() { // this is the "enclosing scope" of bar
var a = 4 <-----------+
|
var b = a // refers to --+
function bar() {
var a = 7 <-----------+
|
var c = a // refers to --+
}
}
this
的行为与上面示例中a
的行为完全相同。
function
范围隐式定义this
的引用,但ES2015 lambda范围和块范围不。如果它们是明确的,那么这些定义会是什么样的:
function foo() { // this is the enclosing scope of baz and the block below
var this = ... <-----------+--+
| |
var b = this // refers to --+ |
|
{ |
var q = this // refers to ---+
}
function bar() { // this is the enclosing scope of baz
var this = ... <-----------+--+
| |
var c = this // refers to --+ |
|
var baz = () => { |
var d = this // refers to ---+
}
}
}
this
在特定范围内引用的内存位置的实际值不是词法定义的;它在运行时设置为调用函数的对象的(内存位置)。但是,另一个引用的阴影总是在词法上定义。
答案 1 :(得分:0)
this
箭头函数是最近的函数范围,意味着使用 function
关键字定义的函数范围发生。
即使箭头函数以某种方式嵌套,这也适用,如
function scope() {
const arrow = a => b => this.foo(a, b);
}
此处有问题的this
是this
的{{1}}。
&#34;玛丽&#34;是调用&#34; on&#34;的对象。功能,应该设置&#34;这个&#34;在&#34; on&#34;玛丽&#34;。最重要的是,箭头功能在&#34; on&#34;中定义。函数在其参数位置(在词法上足够,对吗?),为什么箭头函数不能得到&#34;这个&#34;来自&#34;封闭上下文&#34;的价值,即&#34; on&#34;功能在这里???
是的,scope
中的this
是on
。但是,这并不意味着mary
的实施将其on
的回调调用为mary
,或任何其他特定的this
- 由this
的实施。此外,&#34; context&#34;箭头函数控制它的&#39;这个&#39;不是on
,也不是整个on
语句,也不是一些封闭的mary.on
块,而是功能范围在其中发生。
答案 2 :(得分:0)
我很难解密这个概念,但是最近我全神贯注于它。
因此,要理解这一点,我们应该先了解什么是 scope ?范围是引擎在查找变量时使用的一组规则。因此,在实践中,You don't know JS书中将其描述为引擎与作用域之间的对话非常好。如果您考虑一个简单的左手任务,例如let a = 1;
,则对话将类似于:
现在想象一个场景:console.log(a)
在JavaScript中,有多种定义范围的方法。但是,为了简单起见,我们仅讨论函数范围。 (您也可以通过块来定义范围)
// global scope
function foo(a) {
//foo scope
var b = a * 2;
function bar(c) {
// bar scope
console.log( a, b, c );
}
bar(b * 3);
}
foo( 2 ); // 2 4 12
在上面的示例中,我认为很容易发现两个范围,foo
范围和bar
范围。
如您所见,bar在foo中被调用,并显示a
和b
范围内的3个值foo
和c
bar
中的。之所以能够这样做,是因为范围查找不仅仅发生在当前范围内,它会继续检出其父范围(封闭范围),直到达到全局范围为止。
所以在层次结构中,我们会看到类似的东西
在这种情况下,foo
范围是bar
的包围范围,因为它实际上将bar括在其中。
答案 3 :(得分:-1)
传递给事件发射器回调的函数不会绑定到发射器的作用域,除非你这样做,无论它是传统函数还是胖箭头函数。
当他们说胖箭头函数绑定到词法范围时,他们意味着它不会创建自己的新范围。
考虑:
address