所以...ES6¹(几个小时前恰好是标准化的)为类似于PHP,Python等的函数带来了默认参数。我可以做类似的事情:
function foo (bar = 'dum') {
return bar;
}
foo(1); // 1
foo(); // 'dum'
foo(undefined); // 'dum'
MDN表示在调用时评估参数的默认值。这意味着每次调用函数时,都会再次计算表达式'dum'
(除非实现执行了一些我们不关心的奇怪优化)。
我的问题是,this
如何发挥作用?
let x = {
foo (bar = this.foo) {
return bar;
}
}
let y = {
z: x.foo
}
x.foo() === y.z(); // what?
babel转换器目前正在评估它为false
,但我没有得到它。如果他们真的在通话时评估,那么:
let x = 'x from global';
function bar (thing = x) {
return thing;
}
function foo () {
let x = 'x from foo';
return bar();
}
bar() === foo(); // what?
babel转换器目前正在评估它为true
,但我没有得到它。为什么bar
在x
内部调用foo
时未foo
?
<子>
1 - 是的我知道它是ES2015
2 - Example A
3 - Example B
答案 0 :(得分:11)
我的问题是,
this
如何发挥作用?我不明白。它们是否真的在通话时进行评估?
是的,在呼叫时评估参数初始值设定项。 It's complicated,但步骤基本如下:
thisBinding
is initialised arguments
对象绑定undefined
初始化let
和const
变量的绑定因此,参数初始化者可以访问调用的this
和arguments
,以及之前初始化的其他参数,以及其“上限”词法范围内的所有内容。它们不受函数体中声明的变量的影响(尽管它们受所有其他参数的影响,即使它们的时间死区也是如此)。
怎么样:
function bar (thing = x) {} { let x = 'x from foo'; return bar(); }
我不明白。为什么
bar
在调用时不会从x
获取foo
在foo
内?
因为x
是bar
无法访问的本地变量。我们很幸运他们是not dynamically scoped!参数初始化程序不在调用站点评估,而是在被调用函数的作用域内评估。在这种情况下,x
标识符将解析为全局x
变量。
答案 1 :(得分:0)
当他们说'#34;在通话时评估#34;时,我认为他们指的是按姓名调用表达。以下是babel如何输出您的第三个例子:
'use strict';
var x = 'x from global';
function bar() {
var thing = arguments[0] === undefined ? x : arguments[0];
return thing;
}
function foo() {
var x = 'x from foo';
return bar();
}
bar() === foo(); // what?
由于var x
是在bar
的词法范围内从全局范围继承的,因此它是使用它的范围。
现在,请考虑以下事项:
let i = 0;
function id() {
return i++;
}
function bar (thing = id()) {
return thing;
}
console.info(bar() === bar()); // false
哪个转化为
"use strict";
var i = 0;
function id() {
return i++;
}
function bar() {
var thing = arguments[0] === undefined ? id() : arguments[0];
return thing;
}
console.info(bar() === bar()); // false
注意这里,id
在函数内部被称为,而不是在函数定义时被缓存和记忆,因此调用 - 按名称而不是按值调用。
所以行为 在第二个例子中实际上是正确的。在y.foo
查找时,Javascript中没有this
,因为y.z()
是动态作用域(即它根据给定函数调用的接收者而有所不同) this.foo
,它会在y
中查找,y.z()
将返回undefined
,而x.foo()
只返回foo
函数本身。
如果您执行想要绑定到接收者,则可以在分配时将foo
绑定到x
。然后它应该按预期工作。
对不起,如果有任何不清楚的话;请在评论中告诉我,我很乐意澄清! :)