为什么我的两个javascript类实例不相同?

时间:2019-04-25 08:57:42

标签: javascript import equality es6-class

我有一个自定义的“枚举”类TableSourceType(下面给出了父类Enum):

import Enum from './../../components/enum.js';

export default class TableSourceType extends Enum {}

TableSourceType.csv = new TableSourceType('csv');
TableSourceType.sqLite = new TableSourceType('sqLite');
TableSourceType.mySql = new TableSourceType('mySql');

另外,我有“ {” 1个对象实例” foo和“ baa”两个实例,并且希望两个实例都与TableSourceType.sqlite相同且相同。但是,在进行相等比较之后,将得出false

foo === baa

foo.constructor === baa.constructor

如果我比较实例的名称,则会得到true

foo.name === baa.name

我已经检查过我只有一个包含类“ TableSourceType”的源代码文件。该ES6类是通过导入的

import TableSourceType from '../notebooks/treez/src/data/table/tableSourceType.js'

=>为什么要为“相同”导入获得两个不同的构造函数?

从我的主要html文件开始,我有两个<script type="module">块。

在运行时动态添加第二个脚本块,以注入一些用户定义的代码并将某些内容保存在全局变量中。

比较在第一个(“静态”)脚本块中进行。也许以某种方式导致实例不相同?

=>如何确保平等?
=>在哪里可以找到更多信息以更好地理解平等问题?

实际上,我想在switch语句中使用我的自定义类的实例:

switch (this.sourceType) {
        case TableSourceType.csv:
            this.__showAndHideCompontentsForCsv();
            break;
        case TableSourceType.sqLite:
            this.__showAndHideCompontentsForSqLite();
            break;          
        default:
            var message = 'The TableSourceType "' + this.sourceType + '" is not yet implemented.';
            throw new Error(message);
}

该switch语句失败。我希望this.sourceTypeTableSourceType.sqLite相等,但它们不相等。

如果无法确保不同脚本块(?)中的实例相等,那么是否可以在JavaScript中实现自定义“ equals”和“ hashcode”方法?

如果是这样,我将尝试告诉TableSourceType仅根据实例的name属性定义其相等性。

这是我自定义的Enum类:

export default class Enum {

    static get values(){
        var keys = Object.keys(this).filter(key=>!key.startsWith('__'));        
        return keys.map(key=>this[key]);
    }   

    static get names(){
        return this.values.map((value)=>value.name);
    }

    static get importLocation(){
        return this.__importLocation;
    }

    static forName(name){
        for(var type of this.values){
            if(type.name === name){
                return type;
            }
        }
        throw new Error('Unknown value "' + name + '"');
    }

    constructor(name){
        this.name = name;
        if(!this.constructor.__importLocation){
            this.constructor.__importLocation = this.determineImportLocation();
        }                       
    }

    toString(){
        return this.name;
    }

    determineImportLocation(){
        var stack = new Error().stack;
        var lastLine = stack.split('\n').pop();
        var startIndex = lastLine.indexOf('/src/');
        var endIndex = lastLine.indexOf('.js:') + 3;
        return lastLine.substring(startIndex, endIndex);
    }

}

一种解决方法是在switch语句中使用name属性:

switch (this.sourceType.name) {
        case TableSourceType.csv.name:
            this.__showAndHideCompontentsForCsv();
            break;
        case TableSourceType.sqLite.name:
            this.__showAndHideCompontentsForSqLite();
            break;          
        default:
            var message = 'The TableSourceType "' + this.sourceType + '" is not yet implemented.';
            throw new Error(message);
}

但是,我希望使用switch语句的原始版本。

1 个答案:

答案 0 :(得分:0)

我希望自定义类文件的内容只能执行一次,因为导入之前已经解决了。多亏了Dani R,我发现该代码实际上执行了两次。

遵循TableSourceType的改编代码对我有用:

import Enum from './../../components/enum.js';

export default class TableSourceType extends Enum {}

if(window.TableSourceType){
    TableSourceType = window.TableSourceType;
} else {
    TableSourceType.csv = new TableSourceType('csv');
    TableSourceType.sqLite = new TableSourceType('sqLite');
    TableSourceType.mySql = new TableSourceType('mySql');
    window.TableSourceType = TableSourceType;
}

如果有一种更优雅的方法来确保平等,请告诉我。