So... ES6¹ (which happens to be standardized a few hours ago) brings default parameters for functions similar to those in PHP, Python etc. I can do stuff like:
function foo (bar = 'dum') {
return bar;
}
foo(1); // 1
foo(); // 'dum'
foo(undefined); // 'dum'
MDN says that the default value for the parameter is evaluated at call time. Which means each time I call the function, the expression 'dum'
is evaluated again (unless the implementation does some weird optimizations which we don't care about).
My question is, how does this
play into this?
let x = {
foo (bar = this.foo) {
return bar;
}
}
let y = {
z: x.foo
}
x.foo() === y.z(); // what?
The babel transpiler currently evaluates² it as false
, but I don't get it. If they are really evaluated at call time, what about this:
let x = 'x from global';
function bar (thing = x) {
return thing;
}
function foo () {
let x = 'x from foo';
return bar();
}
bar() === foo(); // what?
The babel transpiler currently evaluates³ it as true
, but I don't get it. Why does bar
not take the x
from foo
when called inside foo
?
1 - Yes I know it is ES2015.
2 - Example A
3 - Example B
In Python, a default parameter is defined with a fallback value as a default argument. Such parameters are optional during a function call. If no argument is provided, the default value is used, and if an argument is provided, it will overwrite the default value.
The default parameter is a way to set default values for function parameters a value is no passed in (ie. it is undefined ). In a function, Ii a parameter is not provided, then its value becomes undefined . In this case, the default value that we specify is applied by the compiler.
A default argument is a value provided in a function declaration that is automatically assigned by the compiler if the calling function doesn't provide a value for the argument. In case any value is passed, the default value is overridden.
The default arguments are given in the function prototype. Compiler uses the prototype information to build a call, not the function definition. The default arguments are given in the function prototype and should be repeated in the function definition.
My question is, how does
this
play into this? I don't get it. Are they are really evaluated at call time?
Yes, the parameter initializers are evaluated at call time. It's complicated, but the steps are basically as follows:
thisBinding
is initialised
arguments
object is created an boundundefined
let
and const
variables in the function body are createdSo parameter initialisers do have access to the this
and the arguments
of the call, to previously initialised other parameters, and everything that is in their "upper" lexical scope. They are not affected by the variables declared in the function body (though they are affected by all the other parameters, even if in their temporal dead zone).
what about this:
function bar (thing = x) {} { let x = 'x from foo'; return bar(); }
I don't get it. Why does
bar
not take thex
fromfoo
when called insidefoo
?
Because x
is a local variable that bar
does not have access to. We're so lucky that they are not dynamically scoped! The parameter initialisers are not evaluated at the call site, but inside the called function's scope. In this case, the x
identifier is resolved to the global x
variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With