admin管理员组文章数量:1313082
So here is the code snippet from this modern JavaScript tutorial:
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(
student => alert(this.title + ': ' + student)
);
}
};
group.showList();
The tutorial tries to explain this
in an arrow function, and it says:
Here in forEach, the arrow function is used, so
this.title
in it is exactly the same as in the outer method showList. That is: group.title.
We know this
in an arrow function is determined lexically. So the scope chain should be:
global--> showList-->forEach-->arrow function
In this case, the outer scope of arrow function should be forEach
instead of showList
. Thus this
in an arrow function is exactly the same as in forEach
, which should be undefined
since there is no thisArg
passed to forEach
. But in fact, this
is group
, which means it is exactly the same as in showList
.
So, it seems forEach
doesn't hold a scope in this case? I am confused.
So here is the code snippet from this modern JavaScript tutorial:
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(
student => alert(this.title + ': ' + student)
);
}
};
group.showList();
The tutorial tries to explain this
in an arrow function, and it says:
Here in forEach, the arrow function is used, so
this.title
in it is exactly the same as in the outer method showList. That is: group.title.
We know this
in an arrow function is determined lexically. So the scope chain should be:
global--> showList-->forEach-->arrow function
In this case, the outer scope of arrow function should be forEach
instead of showList
. Thus this
in an arrow function is exactly the same as in forEach
, which should be undefined
since there is no thisArg
passed to forEach
. But in fact, this
is group
, which means it is exactly the same as in showList
.
So, it seems forEach
doesn't hold a scope in this case? I am confused.
- because you assign or create those methods in the scope of showList and lambdas share scope in js, also those cb get invoked not called ^^ no scope binding - furthermore arrow functions ignore bindings – Estradiaz Commented Jan 2, 2020 at 12:34
-
The
forEach()
and the arrow function are one and the same scope. The scope of theforEach()
is informed by the type of function (arrow vs. conventional) you pass to it. – Mitya Commented Jan 2, 2020 at 12:35 -
Why arrow function is not in
forEach
scope?It should be from the perspective of lexical,right?I mean it just the same asfunction( ){ ( )=>{ } }
(here the function isforEach
) – Chor Commented Jan 2, 2020 at 12:41 - @Estradiaz arrow functions ignore bindings ,but its this will be the same as in its outer scope,which in this question is forEach – Chor Commented Jan 2, 2020 at 12:42
- Hmm isnt it that those arrow functions are created in showList and then passed to forEach where it gets called like cb.call(undefined, ...args), but as those are arrow functions they keep there scope bindings to parent ctx, those are passed as callbacks not created in the scope of foreach – Estradiaz Commented Jan 2, 2020 at 13:10
4 Answers
Reset to default 3So the scope chain should be:
global--> showList-->forEach-->arrow function
I think you are confused what "scope" means. It's a variable scope, in code typically delimited with braces {…}
, the region in which any identifier always refers to the same variable.
There is no "forEach
scope". It's just a function call. Just like there is no scope for the parameter list of the alert(…)
call. There are only three scopes in your example:
global --> showList --> anonymous arrow function
There is also the call stack, outlining which function calls led to the execution of the current code. This does indeed contain forEach
, which is calling the arrow function, which in turn will call the alert
function. But this does not correspond to the scope in JavaScript (for which you will see more examples when learning about closures), which is why JavaScript is said to have lexical scope and not dynamic scope (where identifiers are resolved dynamically depending on where a function was called).
The error occurs because forEach runs functions with this=undefined by default, so the attempt to access undefined.title is made.
That doesn’t affect arrow functions, because they just don’t have this.
source https://javascript.info/arrow-functions
As we remember from the chapter Object methods, "this", arrow functions do not have this. If this is accessed, it is taken from the outside.
The outside function in this case is showList
as you would realise that forEach is not a wrapping function for arrow function here instead it is just a call to a function which takes a callback.
Instead showList
is the wrapping function. Hence it inherits this from showList
Perhaps this example will help you understand better:
'use strict';
function hello(greet) {
greet()
}
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
hello(() => console.log("Hello " + this.title))
}
};
group.showList();
Lexical scope is determined by where a function is defined.
You are passing the arrow function to forEach
, so its scope has nothing to do with forEach
.
It is the same reason that in this example, the function logs "one" and not "two":
function one() {
const value = "one";
two( function() { console.log(value); } );
}
function two(argument) {
const value = "two";
argument();
}
one();
Scope is only created when an object/function is created (in this case).
In the case of .forEach
, you are merely calling a function that is already created by the engine, meaning you are not creating any scopes when calling .forEach
.
Conversely, when you define:
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(
student => alert(this.title + ': ' + student)
);
}
};
It translates to:
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList: function() {
this.students.forEach(
student => alert(this.title + ': ' + student)
);
}
};
You are creating a function named "showList", and therefore you are creating a scope.
Before the showList()
function is created, you created the group
object, thus creating another scope, which, in this case, is the parent scope of showList()
.
Therefore, inside the showList()
function, its this
value is the group
object.
本文标签:
版权声明:本文标题:javascript - Why in this code snippet is the outer scope of the arrow function in `showList` instead of `forEach`? - Stack Overf 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741934845a2405790.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论