【问题标题】:TypeScript Handbook: class static side example overcomplicationTypeScript 手册:类静态示例过度复杂化
【发布时间】:2015-12-29 13:02:57
【问题描述】:

Classes -> Advanced Techniques 部分http://www.typescriptlang.org/Handbook#classes-advanced-techniques 中遇到示例

class Greeter {
    static standardGreeting = "Hello, there";
    greeting: string;
    greet() {
        if (this.greeting) {
            return "Hello, " + this.greeting;
        }
        else {
            return Greeter.standardGreeting;
        }
    }
}

var greeter1: Greeter;
greeter1 = new Greeter();
alert(greeter1.greet());

var greeterMaker: typeof Greeter = Greeter;
greeterMaker.standardGreeting = "Hey there!";
var greeter2:Greeter = new greeterMaker();
alert(greeter2.greet());

及解释:

接下来,我们直接使用类。在这里,我们创建了一个名为“greeterMaker”的新变量。这个变量将保存类本身,或者说它的构造函数。这里我们使用'typeof Greeter',即“给我 Greeter 类本身的类型”而不是实例类型。或者,更准确地说,“给我一个叫做 Greeter 的符号的类型”,也就是构造函数的类型。此类型将包含 Greeter 的所有静态成员以及创建 Greeter 类实例的构造函数。我们通过在 'greeterMaker' 上使用 'new' 来展示这一点,创建 'Greeter' 的新实例并像以前一样调用它们。

我的问题:引入greeterMaker变量的目的是什么?最终,它只包含对 Greeter 类的引用。

我们可以在下面写代码,

Greeter.standardGreeting = "Hey there!";
var greeter2:Greeter = new Greeter();
alert(greeter2.greet());

收到相同的结果,不要把自己与奇怪的外观混淆

var greeterMaker: typeof Greeter = Greeter;

我在这里遗漏了什么吗? 构造var maker: typeof Foo = Foo;真的有用吗?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    我认为您的代码是正确且简单的,但他们采取了中间步骤,即先将 Greeter 类型分配给变量,然后再对其进行操作。

    剖析那行代码,他们只是在说:

    var greeterMaker // there is a variable named greeterMaker
                    : typeof Greeter // the static type of this variable is a constructor function for the Greeter class;
                                     = Greeter; // Assign the value of Greeter (the constructor function) to the variable greeterMaker
    

    所以说到底,greeterMakerGreeter 是同一个东西。 (因为代码是在做var greeterMaker = Greeter;

    我只能假设他们的示例这样做只是为了证明您可以将“类型的类型”分配为变量的静态类型。 换句话说,var greeterMaker: typeof Greeter; 表示greeterMaker 的静态类型是Greeter 的构造函数,而不是Greeter 的实例,这就是示例的值。

    【讨论】:

    • 谢谢!你让我意识到我正在以错误的顺序阅读这行代码(我的是 var greeterMaker: (typeof Greeter = Greeter); )。但是,我仍然想知道为什么我们要使用这样的构造,在这种情况下是greeterMaker。我觉得我需要阅读他们的解释和你的答案至少 10 次以使一切清楚:)
    • 原因是为了证明您可以传递并可能将 Greeter 重命名为 Yesman 之类的其他名称,只需说出 var Yesman: typeof Greeter = Greeter
    • 但奇怪的是你不能var yesman:Yesman = new Yesman();
    【解决方案2】:

    我对这个确切的例子也困惑了好几个小时。在示例中,他们想展示使用new Greeter() 实例化类和使用typeof Greeter 之间的区别。令人困惑的部分是他们跟在

    let greeter2: Greeter = new greeterMaker();
    这会跳过/隐藏差异。暂时忽略greeter2 行,只关注下面的代码,因为这是可以看出差异的地方。

    let greeter1: Greeter = new Greeter(); // var greeter1 = new Greeter();
    
    let greeterMaker: typeof Greeter = Greeter; // var greeterMaker = Greeter;
    

    如果您记录greeter1 和greeterMaker,那么该示例是有意义的,因为您可以看到区别:new Greeter() 是对象类 Greetertypeof Greeter 是类 Greeter 构造函数

    console.log(greeter1); // Greeter{} <-- the greeter object
    
    console.log(greeterMaker);
    // function Greeter() {} <-- class Greeter's constructor function
    // console.log(Greeter) results in the same: function Greeter(){}
    

    在 greeter1 日志中看到 Greeter{} 对象可能仍然令人困惑(可以在控制台中展开以显示所有类成员)

    Greeter {}
        └─  __proto__: Object
            ├─  constructor: Greeter()
            ├─  greet: ()
            └─  __proto__: Object
    

    但是 greeterMaker 控制台日志只显示构造函数的 JavaScript 代码

    function Greeter() {
    }  
    

    如果您查看示例上方的段落(来自此问题中的链接),它开始变得有意义。

    这里,'var Greeter' (在本例中为'var greeter1') 将被分配构造函数。当我们调用“new”并运行这个函数时,我们会得到一个类的实例。

    因此我们在记录greeter1时看到控制台中的完整对象(构造函数已经运行并且实例已创建,而greeterMaker仅向我们展示了构造函数,它仍然必须被调用才能运行才能创建 Greeter 类的实例。

    现在回到

    let greeter2: Greeter = new greeterMaker();
    console.log(greeter2.greet());
    

    like Greeter() 我们不能直接调用greeterMaker().greet() - 我们会得到一个错误

    console.log(greeterMaker().greet());
    // Value of type 'typeof Greeter' is not callable. Did you mean to include 'new'?
    
    console.log(Greeter().greet());
    // Value of type 'typeof Greeter' is not callable. Did you mean to include 'new'?
    

    Greeter()greeterMaker() 引用了不调用“new”就无法访问的构造函数。因此,该示例显示您可以使用new Greeter() 实例化一个类,或者使用typeof Greeter 创建该类的副本,然后可以使用new greeterMaker() 调用该类。

    我意识到这是一篇旧帖子,但我遇到了这个问题,并认为我可以对此进行更多说明,以防有人需要有关此示例的更多信息。干杯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-24
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      相关资源
      最近更新 更多