Typescript 错误引用 _this

Typescript mis-reference to _this

我试图在 TypeScript 中为 String.Prototype 定义一些 属性:

Object.defineProperty(String.prototype, 'test', {
    value: () => {
        console.log("this is a test over text " + this);
    }
})

javaScript原型中,this指调用方法的对象(在本例中为字符串值)。但是文件的编译输出是:

var _this = this;
Object.defineProperty(String.prototype, 'test', {
    value: function () {
        console.log("this is a test over text " + _this);
    }
});

TypeScript 编译器添加变量 _this 并引用它。

这是错误还是我的实现有问题?

Is that a bug or there is a problem in my implementation?

不,这就是 TypeScript 的 arrow functions 工作方式:在箭头函数中,this 是从创建函数的上下文中继承的,而不是由它的调用方式设置的。 (箭头函数也在 ES2015 中,至少部分受到 CoffeeScript 的“粗箭头”函数的启发;我不知道 TypeScript 的历史,也不知道它是否也是 ES2015 箭头函数的一部分灵感,反之亦然。)

引用上面的规范 link:

A function expression introduces a new dynamically bound this, whereas an arrow function expression preserves the this of its enclosing context.

Arrow function expressions are particularly useful for writing callbacks, which otherwise often have an undefined or unexpected this.

In the example

class Messenger {  
    message = "Hello World";  
    start() {  
        setTimeout(() => alert(this.message), 3000);  
    }  
};

var messenger = new Messenger();  
messenger.start();

the use of an arrow function expression causes the callback to have the same this as the surrounding 'start' method.

如果您希望 this 取决于函数的调用方式,请不要使用箭头函数,请使用 function:

Object.defineProperty(String.prototype, 'test', function() {
    console.log("this is a test over text " + this);
})

还要注意 Object.defineProperty 的第三个参数应该是 属性 描述符,而不是函数。您的意思可能是:

Object.defineProperty(String.prototype, 'test', {
    value: function() {
        console.log("this is a test over text " + this);
    }
});

TypeScript 转译器doesn't change that at all;调用 "testing".test() 输出 "this is a test of text testing":

Object.defineProperty(String.prototype, 'test', {
    value: function() {
        snippet.log("this is a test over text " + this);
    }
});
"testing".test();
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>