Подтвердить что ты не робот

Окружная зависимость ES6

Это проблема, с которой я сталкиваюсь довольно часто, и я надеялся найти правильный способ справиться с ней.

Итак, у меня есть такая настройка:

parent.js:

export default {
  x: 1
}

a.js:

import parent from 'parent.js'
export default parent.extend(a, { title: 'a' })

b.js:

import parent from 'parent.js'
export default parent.extend(b, { title: 'b' })

Прохладный, теперь у меня есть дети. Но я решил, что хотел бы иметь функцию в parent.js, которая проверяет, является ли объект экземпляром a или b.

Итак, я могу сделать это:

parent.js:

import a from 'a'
import b from 'b'

export default {
  x: 1,
  checkType (obj) {
    if (obj instanceof a) {
      return 'a'
    } else if (obj instanceof b) {
      return 'b'
    }
  }
}

Хорошо теперь, что круговая зависимость. Есть ли элегантный способ справиться с этим?

4b9b3361

Ответ 1

Наличие логики в родительском классе, который знает о подклассах, является серьезным анти-шаблоном. Вместо этого добавьте методы в подклассы, возвращающие тип. например, в a.js:

import parent from 'parent.js';
export default parent.extend(a, { title: 'a', checkObj() { return 'a'; }});

Если желаемое возвращение из checkObj всегда является значением свойства title, то, конечно, просто:

// parent.js
export default {
  x: 1,
  checkObj() { return this.title; }
}

Я точно не знаю, что здесь делает extend. Я предполагаю, что это какой-то механизм подкласса.

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

Ответ 2

Если вы можете использовать классы es6, вы можете воспользоваться вызовом super() в конструкторе. Я часто буду делать что-то вроде этого:

Parent.js

export default class {
    constructor(options, child) {
        this.child = child;
        this.x = 1;
    }

    checkType() {
        return this.child;
    }
}

A.js

import Parent from './Parent';  

export default class extends Parent {
    constructor(options) {
        super(options, 'a');
    }
}

B.js

import Parent from './Parent';  

export default class extends Parent {
    constructor(options) {
        super(options, 'b');
    }
}

Если вы не хотите использовать классы, возможно, вам нужен более FP-стиль. Вы можете сделать родительский элемент функцией:

parent.js

export default function(child) {
    return {
        x: 1,
        checkType (obj) {
            return child; 
        }
        extend (something) {
            // assuming the returns something as you said
        }
    }
}

a.js

import parent from 'parent.js'
export default parent('a').extend(a, { title: 'a' })

b.js

import parent from 'parent.js'
export default parent('b').extend(b, { title: 'b' })