es6模板字符串+短对象文字转换失败[gulp,babel]

时间:2016-10-24 16:45:46

标签: javascript syntax ecmascript-6 babeljs

我有一个非常小的ES6代码:

var name = "MyName";
var version = "1.2.3";

var theThing = {
  name,
  version,
  run: () => {
    console.log(`You're using ${this.name}@${this.version}`);
  }
};

theThing.run();

当我在浏览器控制台(chrome 53)中运行它时,我得到了预期的结果:You're using MyName@1.2.3被记录到控制台。两个模板字符串都与缩短的对象文字语法一起使用。

但是,当我尝试使用gulp / babel将此代码转换为ES5时,使用最基本的设置(取自here):

const gulp = require('gulp');
const babel = require('gulp-babel');

gulp.task('default', () => {
    return gulp.src('src/app.js')
        .pipe(babel({
            presets: ['es2015']
        }))
        .pipe(gulp.dest('dist'));
});

我得到以下输出:

"use strict";

var name = "MyName";
var version = "1.2.3";

var theThing = {
  name: name,
  version: version,
  run: function run() {
    console.log("You're using " + undefined.name + "@" + undefined.version);
  }
};

theThing.run();

正如您所看到的,它正在调用undefined.name而不是this.name,我完全不知道为什么thisundefined取代。当然,此代码无法按预期工作:

VM329:8 Uncaught TypeError: Cannot read property 'name' of undefined(…)

符合ES6标准(chrome53中ES6的原始实现正常工作)。

您还可以在Babel REPL

中查看此问题

我做错了什么 - 或者它是巴贝尔的错误?

4 个答案:

答案 0 :(得分:2)

原始来源中的

尝试替换

var theThing = {
  name,
  version,
  run: () => {
    console.log(`You're using ${this.name}@${this.version}`);
  }
};

通过

var theThing = {
  name,
  version,
  run: function () {
    console.log(`You're using ${this.name}@${this.version}`);
  }
};

箭头语法功能改变了this的工作方式

答案 1 :(得分:2)

箭头功能不会绑定到this(请参阅here)。因此,当你定义函数时,对象还没有存在......所以Babel并不了解上下文。

摆脱箭头功能将解决它。

答案 2 :(得分:1)

由于词法绑定,箭头函数this指向window。当您致电theThing.run()时,您实际上会在模板中获得window.namewindow.version。如果重命名全局变量,它将不起作用:

var n = "MyName";
var v = "1.2.3";

var theThing = {
  name: n,
  version: v,
  run: () => {
    console.log(`You're using ${this.name}@${this.version}`);
  }
};

theThing.run();

要解决此问题,请不要使用箭头功能:

    var n = "MyName";
    var v = "1.2.3";

    var theThing = {
      name: n,
      version: v,
      run() {
        console.log(`You're using ${this.name}@${this.version}`);
      }
    };

    theThing.run();

答案 3 :(得分:0)

正确答案包括2点:

  • 箭头函数和经典ES5函数具有完全不同的this绑定。经典函数中的this是非常动态的(在运行时确定,无论它在何处定义),而在箭头中,它是词法绑定的(绑定在它放置的位置,运行时没有影响)在那,运行时已经太晚了,无法改变它。词法范围使箭头函数借用 this来自最近的封闭经典函数(如果存在)。如果不存在,则取自全球范围......
  • 如果不是严格模式,则会window。如果处于严格模式,则会undefined

......这正好回答了上述问题。