Почему мои два экземпляра класса javascript не идентичны? - PullRequest
0 голосов
/ 25 апреля 2019

У меня есть пользовательский класс "Enum" 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');

Кроме того, у меня есть "два" экземпляра объекта 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">blocks.

Второй блок сценария добавляется динамически во время выполнения для вставки некоторого пользовательского кода и сохранения некоторых вещей в глобальной переменной.

Сравнение происходит в первом («статическом») блоке скрипта.Может быть, это как-то делает экземпляры не идентичными?

=> Как я могу обеспечить равенство?
=> Где я могу найти больше информации, чтобы лучше понять эту проблему равенства?

На самом деле я хотел бы использовать экземпляры своего пользовательского класса воператор 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.sourceType и TableSourceType.sqLite будут равны, но это не так.

Если невозможно обеспечить равенство для экземпляров в разных блоках скрипта (?) ... возможно ли реализовать что-то вроде пользовательских методов "equals" и "hashcode" в JavaScript?

Если это так, я бы попытался указать 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);
    }

}

Обходным путем будет использование свойства name в операторе switch:

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 голосов
/ 25 апреля 2019

Я ожидал, что содержимое файла моего пользовательского класса будет выполнено только один раз, потому что импорт уже был разрешен ранее. Благодаря 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;
}

Если есть более элегантный способ обеспечить равенство, пожалуйста, дайте мне знать.

...