使用相同的参数名称作为ES6中的默认参数

lag*_*lex 8 javascript ecmascript-6 babeljs

这个ES6代码:

const log = () => console.log('hi');
const parent = (log = log) => log();
parent();
Run Code Online (Sandbox Code Playgroud)

透明至:

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();
};
parent();
Run Code Online (Sandbox Code Playgroud)

给出错误:

    return log();
           ^
TypeError: log is not a function
Run Code Online (Sandbox Code Playgroud)

问题是这一行:

const parent = (log = log) => log();
Run Code Online (Sandbox Code Playgroud)

因为参数名称与其默认参数相同.

这有效:

const log = () => console.log('hi');
const parent = (logNow = log) => logNow();
parent();
Run Code Online (Sandbox Code Playgroud)

这是Babel中的错误还是规范本身不允许这样做?

web*_*deb 4

看起来这是 ES6 的预期行为。在Chrome控制台上测试,也出现错误。

ES6 规范指出了这一点:

  1. 令parameterNames 为形式的BoundNames。 http://www.ecma-international.org/ecma-262/6.0/#sec-functiondeclarationinstantiation

这意味着当你创建函数时,ES6 会做与 babel 基本相同的事情,它将在新上下文中管理参数的分配。

a在 javascript 中,当您在封闭作用域中创建变量时,全局变量将无法再被访问,因为 JS 会从 AST 中最近的可能作用域中a获取变量。a

简单的例子:

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;
  console.log(a)
}
test() // undefined
Run Code Online (Sandbox Code Playgroud)

为什么它不取外部 a 的值,然后将其分配给内部 a ,是因为hoisting,基本上它是这样做的:

function test() {
  var a; // the address for the variable is reserved at compile time
  a = a; // run-time assignment 
}
Run Code Online (Sandbox Code Playgroud)

它获取函数的所有变量声明并将其提升到函数的开头。

这就是为什么这样的事情会起作用的原因:

function hoistingTest(n, m = 2) {
  // return immediately
  return multi(n);

  // This declaration will be hoisted to the begin of the body
  function multi(n) { return m * n }
}
Run Code Online (Sandbox Code Playgroud)