在 Javascript ECMAScript 6 中从类名创建对象

Posted

技术标签:

【中文标题】在 Javascript ECMAScript 6 中从类名创建对象【英文标题】:Create object from class name in JavasScript ECMAScript 6 【发布时间】:2015-10-24 22:47:28 【问题描述】:

我想使用 ES6 创建对象工厂,但旧式语法不适用于 new。

我有下一个代码:

export class Column 
export class Sequence 
export class Checkbox 

export class ColumnFactory 
    constructor() 
        this.specColumn = 
            __default: 'Column',
            __sequence: 'Sequence',
            __checkbox: 'Checkbox'
        ;
    

    create(name) 
        let className = this.specColumn[name] ? this.specColumn[name] : this.specColumn['__default'];
        return new window[className](name); // this line throw error
    


let factory = new ColumnFactory();
let column = factory.create('userName');

我做错了什么?

【问题讨论】:

仅供参考,手动编码的 ES5 版本在这里工作:jsfiddle.net/jfriend00/4x45gqLt。可能值得看看 babeljs 产生了什么,看看有什么不同。显然 Column 不是全局的(因此不在 window 对象上),但生成的 ES5 代码肯定会显示给你。 嗯,window[className] 从来没有可靠地工作过。 【参考方案1】:

不要把类名放在那个对象上。将类本身放在那里,这样您就不必依赖它们是全局的并且可以通过window 访问(在浏览器中)。

顺便说一句,没有充分的理由让这个工厂成为一个类,你可能只会实例化它一次(单例)。让它成为一个对象:

export class Column 
export class Sequence 
export class Checkbox 

export const columnFactory = 
    specColumn: 
        __default: Column,    // <--
        __sequence: Sequence, // <--
        __checkbox: Checkbox  // <--
    ,
    create(name, ...args) 
        let cls = this.specColumn[name] || this.specColumn.__default;
        return new cls(...args);
    
;

【讨论】:

实际上很棒的工厂示例,在我的项目中使用它:)【参考方案2】:

有一个小而肮脏的方法可以做到这一点:

function createClassByName(name,...a) 
    var c = eval(name);
    return new c(...a);

您现在可以像这样创建一个类:

let c = createClassByName( 'Person', x, y );

【讨论】:

我喜欢这个评估解决方案 我也是+1。我知道每个人都谴责 eval 但只要您完全控制可能的值,它就是最简单、最灵活的解决方案。 我喜欢这个 eval,但现在有问题,无法在 es6 类方法中使用 eval 创建变量 我认为使用 eval() developer.mozilla.org/en-US/docs/Web/javascript/Reference/… 存在安全风险。 eval 太棒了【参考方案3】:

问题是类不是窗口对象的属性。你可以有一个属性“指向”你的类的对象:

class Column 
class Sequence 
class Checkbox 
let classes = 
  Column,
  Sequence,
  Checkbox 


class ColumnFactory 
    constructor() 
        this.specColumn = 
            __default: 'Column',
            __sequence: 'Sequence',
            __checkbox: 'Checkbox'
        ;
    

    create(name) 
        let className = this.specColumn[name] ? this.specColumn[name] : this.specColumn['__default'];
        return new classes[className](name); // this line no longer throw error
    


let factory = new ColumnFactory();
let column = factory.create('userName');

export ColumnFactory, Column, Sequence, Checkbox;

【讨论】:

Column 构造函数不是全局的吗? 显然不在 babeljs 中(无法发布 repl,太长)【参考方案4】:

对于那些不使用 ES6 并想知道如何使用字符串创建类的人来说,这是我为使其工作所做的工作。

"use strict";

class Person 
    constructor(x, y) 
        this.x = x;
        this.y = y;
    

window.classes = ;
window.classes.Person = Person;

document.body.innerText = JSON.stringify(new window.classes["Person"](1, 2));

如您所见,最简单的方法是将类添加到对象中。

这是小提琴: https://jsfiddle.net/zxg7dsng/1/

这是一个使用这种方法的示例项目: https://github.com/pdxjohnny/dist-rts-client-web

【讨论】:

【参考方案5】:

我更喜欢这种方法:

allThemClasses.js

export class A 
export class B 
export class C 

script.js

import * as Classes from './allThemClasses';

const a = new Classes['A'];
const b = new Classes['B'];
const c = new Classes['C'];

【讨论】:

【参考方案6】:

我知道这是一篇旧帖子,但最近我遇到了关于如何动态实例化类的相同问题

我正在使用webpack,所以在documentation 之后,有一种方法可以使用 import() 函数动态加载模块

js/classes/MyClass.js

class MyClass 
    test = null;
    constructor(param) 
        console.log(param)
        this.test = param;
    

js/app.js

var p = "example";
var className = "MyClass";

import('./classes/'+className).then(function(mod) 
    let myClass = new mod[className](p);
    console.log(myClass);
, function(failMsg) 
    console.error("Fail to load class"+className);
    console.error(failMsg);
);

注意:此方法是异步的,我无法确定它的性能成本, 但它在我的简单程序上完美运行(值得一试^^)

Ps顺便说一句,我是 Es6 的新手(几天),我更像是 C++/php/Java 开发人员。

我希望这对遇到这个问题的人有所帮助,这不是一个坏习惯^^"。

【讨论】:

以上是关于在 Javascript ECMAScript 6 中从类名创建对象的主要内容,如果未能解决你的问题,请参考以下文章

学习教程| 一 ECMAScript 6 简介

Javascript ES6 特性概述(即ECMAScript 6和ES2015+)

《01》ECMAScript 6 简介

在 Javascript ECMAScript 6 中从类名创建对象

JavaScript ES6功能概述(ECMAScript 6和ES2015 +)

javascript ECMAScript 6中符号的用途是啥? [复制]