【问题标题】:Nested ES6 classes?嵌套 ES6 类?
【发布时间】:2015-02-28 16:59:33
【问题描述】:

似乎可以在构造函数中嵌套一个类,然后可以从类中的任何位置实例化,这是官方的吗?

[编辑] 例如,

class C {

    constructor() {
        class D {
            constructor() { }
        }
    }

    method() {
        var a = new D();  // works fine
    }

}

//var a = new D();  // fails in outer scope

traceur 生成的 JS https://google.github.io/traceur-compiler/demo/repl.html

$traceurRuntime.ModuleStore.getAnonymousModule(function() {
  "use strict";
  var C = function C() {
    var D = function D() {};
    ($traceurRuntime.createClass)(D, {}, {});
  };
  ($traceurRuntime.createClass)(C, {method: function() {
      var a = new D();
    }}, {});
  return {};
});
//# sourceURL=traceured.js

【问题讨论】:

  • 你能提供一个具体的例子吗?
  • 或者你是怎么发现的?还没有浏览器实现类。
  • 我确定我在某处读到过这篇文章,并且牢记在心 - 被 traceur 破解(参考上面的链接)。
  • 这很可能是 traceur 中的一个错误。

标签: javascript ecmascript-6 traceur


【解决方案1】:

不,在 ES6 中没有嵌套类,如果你的意思是这样的话,类语法中也没有私有成员这样的东西。

当然,您可以将第二个类作为静态属性放在另一个类上,如下所示:

class A {
    …
}
A.B = class {
    …
};

或者你使用额外的作用域:

var C;
{
    class D {
        constructor() { }
    }
    C = class C {
        constructor() { }
        method() {
            var a = new D();  // works fine
        }
    }
}

(traceur 似乎有一个错误,因为它使用提升的var 进行类声明而不是块范围)


使用proposed class field syntax,还可以编写单个表达式或声明:

class A {
    …
    static B = class {
         …
    }
};

【讨论】:

  • 应该是A.B = class B { ..。否则该类将是匿名的。
  • @levi: 匿名类没有什么问题 :-) 当然你可以添加它。
  • @Dakusan 不,这不是 JS 的风格。那是 TypeScript(你可能已经设置为编译为 ES6)。
  • 对于B 类,应在} 之后包含;
  • @JonTrent 您需要引用A 本身,而不是它的实例。您可以使用either A.B or this.constructor.B。我建议避免将类放在原型上。
【解决方案2】:

你可以使用吸气剂:

class Huffman {
  constructor() { /* ... */ }
  static get Node() {
    return class Node {
      constructor() {  
        var API = this;
        API.symbol = 0; API.weight = 0;
        return API;    
      }
    };
  }
  get Node() {
    return Huffman.Node;
  }
  encode() { /* ... */ }
  decode() { /* ... */ }
  /* ... */
}

// usage
huffman = new Huffman;
new huffman.Node;
new Huffman.Node;

Apple 10.10.2 上最新的 Chrome Dev 44.0.2376.0 在控制台中提供的内容

  • new huffman.Node
  • Node {symbol: 0, weight: 0}
  • new Huffman.Node
  • Node {symbol: 0, weight: 0}

在其他新闻中,getter 是让你在 ES6 中做很多很酷的事情的秘诀。

请注意上面的构造打破了instanceofNode(为什么?因为每次get 调用都定义了一个全新的类)。为了不破坏 instanceof 在单个 getter 范围之外定义 Node ,无论是在构造函数中(禁用 Huffman.Node 类属性并导致 instanceof 在单个 Huffman 实例的命名空间内工作,并在此之外中断) ,或在 Huffman 的兄弟或祖先范围内定义 Node(允许 instanceof 在定义 Node 的范围以下的所有范围内工作)。

【讨论】:

  • ……如果打破instanceof/原型链,你也会破坏性能。你真的应该使用huffman.Node = class { constructor(){ this.symbol=0; this.weight=0; } };
  • 我现在倾向于为每个模块/文件编写一个类,尽管我认为如果一个类存在填充另一个类的属性(即,当类的实例是的属性被删除)并且没有被其他类使用,那么我会将类放在同一个模块中 - 这实际上与嵌套类相同(但不完全是,不可能将类嵌套在嵌套类中以这种方式,此时可能是一个嵌套范围)。
  • 等等,你代码中的那些类(以及 OP 想要的)不在 instances 的属性上,但它们与整个类本身相关联。跨度>
  • 非静态get是实例的属性,静态get是类的属性。另一个不错的解决方案是将相关的类放入一个模块中,这样我们就可以拥有一个包含 Encoder、Node 和 Decoder 类的 Huffman 模块。它们都是模块属性,并且都在同一个范围内。
  • 你是说我的question on loading scripts吗?如果否,请在此处评论该答案。不,我对 DI 并没有更深入的想法。
【解决方案3】:

类似的东西?

class A {
    constructor () {
        this.B = class {
            echo () {
                console.log('I am B class');
            }
        }
    }
    echo () {
        this.b = new this.B;
        this.b.echo();
    }
}

var a = new A;

a.echo();

【讨论】:

  • 为您的答案添加更多信息,而不仅仅是代码块
  • 这个选项的缺点(相对于 Bergi 的回答)是,对于 A 类的每个实例,都会有一个包含 B 类定义的属性。
  • 这是这里唯一正确的答案。 this.b = new this.B; 部分很重要。
  • @Ammatwain 你知道使用这个我们需要注意的任何内存影响吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-16
  • 2016-10-03
  • 2017-10-13
  • 2019-10-23
  • 1970-01-01
相关资源
最近更新 更多