【问题标题】:Cannot call private function from constructor in TypeScript无法从 TypeScript 中的构造函数调用私有函数
【发布时间】:2018-09-05 11:28:44
【问题描述】:

我有一个简单的 TypeScript 类,它有一个私有函数,当用户单击一个按钮时应该调用它。点击事件通过构造函数中的jQueryclick()事件绑定

HTML

<div id="foobar">
  <h2>Foo</h2>
  <button type="button">Bar</button>
</div>

TS

$(() => {
    var foo = new Bar($("#foobar"));
})

class Bar {
    private view: JQuery;
    private button: JQuery;

    constructor(view: JQuery) {
            // Fields
        this.view = view;
        this.button = view.find("button");

        // Events
        this.button.click(() => { this.buttonClick() });
    }

    private buttonClick() {
        this.view.find("h2").css("background-color", "red");
    }
}

https://jsfiddle.net/z4vo5u5d/18781/

但是不知何故,在执行脚本时,控制台抱怨buttonClick 不是一个函数。我在这里错过了什么?

我想这是"this" in TypeScript 的问题。但我不知道为什么。

已编辑: 正如@Amadan 提到的:

this.button.click(() => { this.buttonClick() });

incorrectly by jsfiddle翻译成

this.button.click(function () { this.buttonClick(); });

同时,typescriptlang.org/play 上的编译器将其正确翻译为:

var _this = this;
...
this.button.click(function () { _this.buttonClick(); });

【问题讨论】:

  • 我不知道,它看起来像一个错误。我在 typescriptlang.org/play 编译了您的课程,然后将 JavaScript 版本粘贴到您的 TypeScript 课程上,它按预期工作。不知道发生了什么。
  • @Amadan TS 不会将箭头函数转译到其中,TS 会正确转译它。无论 jsfiddle 使用什么产生错误的输出,它都不是 TS 编译器。
  • @zerkms:我认为我们实际上是同意的,只是在不同意的情况下。 TS 无法正确或错误地转换,它是一种语言。 JSFiddle 使用的 TS transpiler 不兼容。在 Node 中使用的 TS 转译器,或者在操场上使用的 TS 转译器,可以正确执行。你不能说它不是一个 TS 转译器,正如你不能说一个有虫的苹果不是一个苹果。
  • 对,我的意思可能是——这不是 tsc 或 TS 语言问题,而是 jsfiddle 问题,应该在那里报告。

标签: typescript


【解决方案1】:

我认为这里的问题是我喜欢称之为范围界定问题。

在旧版本的 TypeScript 中,就像 JSFiddle 使用的那样,this 的范围在您使用它的任何地方都不相同。它是一个动态变量,根据调用位置而变化。按钮事件函数中的this.buttonClick() 计算为按钮本身的buttonClick() 函数,它没有,因为它属于Bar

尝试在您的constructor(view: JQuery) { 下方分配一个const self = this; 值,并在您的构造函数中将所有出现的this 替换为self

这确保self 评估的对象始终是对象本身,而不是当前上下文,这可能不是您的目标。

class Bar {
    private view: JQuery;
    private button: JQuery;

    constructor(view: JQuery) {
        const self = this;

        // Fields
        self.view = view;
        self.button = view.find("button");

        // Events
        self.button.click(() => { self.buttonClick() });
    }

    private buttonClick() {
        this.view.find("h2").css("background-color", "red");
    }
}

That 应该可以完美运行。我以前多次遇到过这个问题。我已经习惯在我编写的每个函数中声明const self = this;

已编辑: 正如@Amadan 提到的:

this.button.click(() => { this.buttonClick() });

incorrectly by jsfiddle翻译成

this.button.click(function () { this.buttonClick(); });

同时,typescriptlang.org/play 上的编译器将其正确翻译为:

var _this = this;
...
this.button.click(function () { _this.buttonClick(); });

【讨论】:

  • JS 箭头函数是词法范围的,不需要创建self 变量,this 保证具有相同的值。
  • @zerkms 正如问题所述,这显然不能保证每个版本的 TypeScript。这个答案是对 OP 问题的有效解决方案,无论他们使用的是 JSFiddle(顺便说一下,据我所知,它使用 TS 1.7.3(!))或其他方式。说“告诉 JSFiddle 更新他们的东西”是不是解决方案。
  • @RickvanOsta 如果一个广泛使用的网站使用的工具版本存在错误,导致该工具不兼容,那么“告诉他们更新他们的东西”是解决方案。
  • “我已经习惯在我编写的每个函数中声明 const self = this;”——这样做没有什么意义:如果你不信任编译器,怎么办你信任2+2 等于4?那条线在哪里?
  • @zerkms 我的意思是我在 JSFiddle 中编写的函数,而不是在我自己的项目中。我不是野蛮人。
猜你喜欢
  • 2016-12-03
  • 2021-09-19
  • 1970-01-01
  • 2014-06-11
  • 2011-04-20
  • 1970-01-01
  • 1970-01-01
  • 2013-08-28
  • 2018-06-02
相关资源
最近更新 更多