我正在学习JavaScript,但有很多我无法理解的东西。在一个在线JavaScript测验中,出现了以下问题:
以下JavaScript代码将记录到控制台:
const a = {};
const b = () => a.a = () => {};
const c = c => '' + c + a.a(b());
const d = console.log.bind(console);
const e = (e => () => d(c(e++)))(0);
try{
e();
}catch(a){
e();
}
花了一些时间来了解每个变量(此处常量)的含义。我开始分析e()
内部try
块中的代码。因此,e
表示闭包,这意味着将使用参数d
调用函数c(0)
,e
将变为1
。据我了解,这里d
基本上代表console.log
函数(但我无法弄清楚为什么他们使用bind
?)。
现在,我知道第一个将被执行c(0)
然后结果被提交到控制台,对吧?让我们看一下函数c
。它返回转换为字符串的第一个参数和a.a(b())
的连接结果。好的,所以a.a(b())
将首先执行,我是对的吗?但是,问题是因为a.a
不是函数,它是未定义的,所以会抛出错误,我们转到catch
。
现在,在catch
块中,所有内容都应该相同,因此a.a
仍然不是函数,应抛出引用错误。但是,当我看到没有抛出任何错误时,它让我感到惊讶,但是控制台实际上记录了1undefined
。为什么?怎么样?
好的,经过一番思考后,我意识到可能在调用a.a(b())
时可能会先执行b()
。按照我的假设,然后函数b
asign引用一个对对象a
的属性a
什么都不做的函数,对吗?但是,a.a
是一个函数,它将在try
块中执行,0undefined
将被记录。
然而,这两个假设都不正确。这里的主要问题是首先执行的是什么?如果我们致电someObject.propertyWhichIsNotAFunction(somethingWhichMakesItAFunction)
,会发生什么?首先执行什么?似乎在try
块中,首先执行一件事,然后在catch
其他事件中执行。这对我来说毫无意义。有什么解释吗?
答案 0 :(得分:1)
这与Why is the value of foo.x undefined in foo.x = foo = {n: 2}?的原因非常相似,只是有点棘手,因为它在执行时抛出TypeError时依赖它。
基本上会发生什么:
a.a
以找出稍后在步骤3 中将被称为的函数。b()
被评估,因为它是一个函数参数及其返回
value成为a.a
评估到的任何内容的实际参数。a.a
的任何内容,并以b()
的返回值作为参数。规范的相关部分在这里:https://www.ecma-international.org/ecma-262/7.0/index.html#sec-function-calls
请注意,调用函数时发生的第一件事是:
- 让 ref 成为评估MemberExpression的结果。
- 让 func 成为?的GetValue(REF)。
醇>
这意味着评估a.a
并将其引用的函数称为func
。第一次a.a
评估为undefined
,因此func
为undefined
,并且https://www.ecma-international.org/ecma-262/7.0/index.html#sec-evaluatedirectcall的第2步会引发TypeError,这是 ArgumentListEvaluation(arguments)
后,调用b()
并为a.a
分配新值,但不会在func
的值之后