为什么 Babel 从对象中解构 属性 时会引入未使用的变量?

Why Babel introduces unused variable when destructuring property from object?

我刚刚查看了源代码的编译脚本,我想我发现了一些奇怪的东西。

这个 ES6 代码:

const data = {someProperty:1, someNamedPropery: 1, test:1};
const { 
  someProperty, // Just gets with 'someProperty' peoperty
  someNamedPropery: changedName, // Works same way, but gets with 'changedName' property
  test: changedNameWithDefault = 1, // This one, introduces new variable and then uses it to compare that to void 0
} = data;

编译为:

"use strict";

const data = {someProperty:1, someNamedPropery: 1, test:1};
var someProperty = data.someProperty,
    changedName = data.someNamedPropery,
    _data$test = data.test,
    changedNameWithDefault = _data$test === void 0 ? 1 : _data$test;

我很好奇为什么 Babel 引入了新变量 _data$test。就不能这样吗?

...
changedNameWithDefault = data.test === void 0 ? 1 : data.test;

它仍然有效。

注意,如果键不存在于 data 变量中或者是 undefined.

,则仅当我尝试分配默认值时才会引入新变量

如果 data.test 足够大,这会影响应用程序性能吗?我想知道垃圾收集器是否会处理它(_data$test 变量)。

Can't it just be something like this?

不,但为什么不这样做有点微妙:如果 test 是一个 accessor 属性,访问它是一个函数调用。解构代码和 Babel 对其的翻译只会调用访问器一次。您的更改会调用它两次。这是一个例子:

const data = {
    someProperty:1,
    someNamedPropery: 1,
    get test() {
        console.log("  test called");
        return 1;
    },
};

function es2015OriginalCode() {
    const { 
        someProperty,
        someNamedPropery: changedName,
        test: changedNameWithDefault = 1,
    } = data;
    console.log(`  changedNameWithDefault = ${changedNameWithDefault}`);
}

function babelCode() {
    "use strict";

    var someProperty = data.someProperty,
        changedName = data.someNamedPropery,
        _data$test = data.test,
        changedNameWithDefault = _data$test === void 0 ? 1 : _data$test;
    console.log(`  changedNameWithDefault = ${changedNameWithDefault}`);
}

function yourCode() {
    "use strict";

    var someProperty = data.someProperty,
        changedName = data.someNamedPropery,
        changedNameWithDefault = data.test === void 0 ? 1 : data.test;
    console.log(`  changedNameWithDefault = ${changedNameWithDefault}`);
}

console.log("ES2015 original code:");
es2015OriginalCode();
console.log("Babel's code:");
babelCode();
console.log("Your code:");
yourCode();
.as-console-wrapper {
    max-height: 100% !important;
}

虽然我们可以通过查看代码看出 test 不是那个特定示例中的访问器 属性,但代码转换通常不适用于那么多的上下文,所以这是翻译该代码的更安全的一般情况方式。