匿名类实例 ---- 这是一个坏主意吗?

IT技术 javascript oop ecmascript-6 javascript-objects anonymous-function
2021-01-17 13:03:01

在 ES6 中我们可以做匿名类:

var entity = class {
}

但我们也可以实例化它:

var entity = new class {
    constructor(name) { this.name = name; }
    getName() { return this.name; }
}('Foo');
console.log(entity.getName()); // Foo

背后做了什么,会带来什么优势,还会带来哪些注意事项?

2个回答

匿名类实例——这是个坏主意吗?

是的,非常糟糕的一个。只是那么糟糕,因为new function() { … }在ES5

这种写作风格导致每次对表达式求值时都会创建一个新的构造函数和原型对象。如果您使用这种方法创建多个对象,它们将无法获得类/原型的任何好处。

如果您打算使用此模式创建单例对象,那么您也失败了。构造函数仍然被创建,它甚至是可访问的 - 可以使用 轻松创建第二个实例new entity.constructor,从而违背了整个目的。

所以永远不要使用它一个简单的对象字面量更容易编写、阅读和实例化:

var entity = {
    name: 'Foo',
    getName() { return this.name; }
};
console.log(entity.name); // Foo

不要被new class模式很常见的其他语言所迷惑,它在那里的工作方式与在 JavaScript 中非常不同。

读者应该注意引用“这种写作风格导致每次计算表达式时都会创建一个新的构造函数和原型对象。如果您使用这种方法创建多个对象,他们将无法获得类/原型的任何好处。” -- 除非我误解了,这是对为每个对象创建匿名类的有效反对意见,但不一定反对使用匿名类来创建多个对象,在这种情况下,他们仍然可以从原型继承中受益。(其他反对意见可能存在也可能不存在。)
2021-03-14 13:03:01
如果你将它用于单身人士,你就没有“失败”。您可以通过简单地克隆它来创建任何对象的第二个实例JavaScript 是一种动态语言,具有自省、评估和可以在运行时修改的标准库。如果您希望阻止恶意或愚蠢的同事访问您的代码,那么您肯定选择了错误的编程语言!
2021-03-17 13:03:01
@alextgordon 使用闭包的对象无法轻松克隆,如果单例的设置逻辑未包含在(构造函数)方法中,则它通常无法运行两次。
2021-03-29 13:03:01
@ninjagecko 是的,一般反对使用class“单身人士”。它甚至不需要匿名。
2021-03-30 13:03:01
您没有提供任何反对使用匿名类的明确论据。类/原型的好处?当使用匿名类时,它们究竟是什么?至于“每次评估时创建一个类”,这完全取决于在程序过程中发生的频率(多少次)。在某些情况下,缺点可能可以忽略不计。但作为一般规则,是的,我建议坚持普通课程。除非你有理由不这样做。
2021-04-02 13:03:01

如果你确切地知道你在做什么,你可能想要匿名类,你正在一个深思熟虑的元编程系统中创建一个类的层次结构(即你想要副本的东西),并且没有其他优雅的扩展解决方案,例如

{
    myImplementation: class extends MyBaseClass {
        someMethod(x) {
            super().someMethod(x);
            insert extended behavior
        }
    }
}

当然,您可以使用一些滥用的魔法函数来实现上述内容Object.assign

{
    myImplementation: extendMagic(mySuper => ({
        someMethod(x) {
            mySuper.someMethod(x);
            insert extended behavior
        }
    }))
}

或者找到一些更好的方法来做你正在做的事情。但是人为的用例偶尔会(尽管很少)存在。

用例从来都不是很好,但是当您需要使用原型继承更难编写的类功能时最引人注目(当然,由于类是原型继承的包装器,您的用例归结为需要语法糖加上es6+ 类特性...你想要构造函数、super、extends 和 staticmethod 等等吗?你是否一直在使用已经存在的类,或者你能用对象和断言来编写所有东西吗?它真的需要吗?是匿名的?这些问题可以帮助你决定)。