我有一个非常小的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
,我完全不知道为什么this
被undefined
取代。当然,此代码无法按预期工作:
VM329:8 Uncaught TypeError: Cannot read property 'name' of undefined(…)
且不符合ES6标准(chrome53中ES6的原始实现正常工作)。
您还可以在Babel REPL。
中查看此问题我做错了什么 - 或者它是巴贝尔的错误?
答案 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.name
和window.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点:
this
绑定。经典函数中的this
是非常动态的(在运行时确定,无论它在何处定义),而在箭头中,它是词法绑定的(绑定在它放置的位置,运行时没有影响)在那,运行时已经太晚了,无法改变它。词法范围使箭头函数借用 this
来自最近的封闭经典函数(如果存在)。如果不存在,则取自全球范围...... window
。如果处于严格模式,则会undefined
......这正好回答了上述问题。