laggingreflex laggingreflex - 3 months ago 7x
Javascript Question

Using same argument name as its default parameter in ES6

This ES6 code:

const log = () => console.log('hi');
const parent = (log = log) => log();

Transpiled to:

var log = function log() {
return console.log('hi');
var parent = function parent() {
var log = arguments.length <= 0 || arguments[0] === undefined ? log : arguments[0];
return log();

Gives error:

return log();
TypeError: log is not a function

The problem is this line:

const parent = (log = log) => log();

Because the argument name is same as its default parameter.

This works:

const log = () => console.log('hi');
const parent = (logNow = log) => logNow();

Is this a bug in Babel or is this not allowed in the spec itself?


Seems like this is the expected behavior of ES6. Tested on the Chrome console, also got an error.

The ES6 spec is saying to that point:

  1. Let parameterNames be the BoundNames of formals.

This means when you create function, ES6 will do basically the same like babel is doing, it will manage the assignment of the params in the new context.

In javascript, when you create a variable a in a closed scope, global a, cannot be accessed anymore, because JS will take the a from the nearest possible scope, in AST.

Simple example:

var a = 1;
function test() {
  // creates the variable a, and try to assign a value to it,
  // because `a` is now available in the scope itself, it will take value of a in the inner scope, not the outer scope one
  var a = a;
test() // undefined

I am not sure, why its not taking the value of outer a, and then assign it to the inner a, but I guess, that the behavior for functions is this:

function test() {
  var a; // the address for the variable is reserved at compile time
  a = a; // run-time assignment 

So instead of giving an address to a local variable at each function call, variables declarations happens at compilation time, and this brings a huge performance benefit.