ES6: доступ к двум различным областям (глобальная и классовая) в одной и той же функции - PullRequest
0 голосов
/ 01 июля 2018

Это довольно сложно объяснить. Прошу прощения за надуманный пример.

Я хочу получить доступ к двум разным областям (глобальным классам и локальным объектам) в одной и той же функции. Указанная функция является объектом-методом.

Я использую babel-preset-react-native, который должен быть ES6 (https://facebook.github.io/react-native/docs/javascript-environment.html).

С учетом следующего примера класса:

class Logic {

  constructor() {
    this.keys = ['Red Key', 'Blue Key'];
  }

  hasKey = (searchKey) => {
    return this.keys.includes(searchKey);
  }

  allowedToEnter = {
    redHouse: () => {
      // some logic
      return true;
    },
    // ...
  };

  houses = [
    {
      name: 'Red House',
      isAccessible: () => {
        return this.hasKey('Red Key');
      },
      shouldAccess__Global: () => {
        return /* wrong scope */this.isAccessible() && this.allowedToEnter.redHouse();
      },
      shouldAccess__Local: function () {
        return this.isAccessible() && /* wrong scope */this.allowedToEnter.redHouse();
      },
    },
    // ...
  ];
}

let logic = new Logic();
console.log(logic.houses[0].shouldAccess__Global());
// returns: isAccessible is not a function
console.log(logic.houses[0].shouldAccess__Local());
// returns: Cannot read property 'redHouse' of undefined

Определение функции стрелки связывает область видимости класса с this. Используя классический синтаксис функции, он связывает this с областью действия своего «владельца», домашнего объекта внутри массива. Я понимаю, что в обоих случаях это правильное поведение.

Существует ли элегантный способ написания метода shouldAccess, дающий доступ к обеим областям?

Возможное решение, которое я придумал, следующее:

shouldAccess__withHelper: function () {
  return this.isAccessible() && this.helper().allowedToEnter.redHouse();
},
helper: () => {
  return this;
},

Это не элегантная мысль. У меня есть большое количество домашних объектов в моем массиве. Предоставление каждому объекту вспомогательной функции - отстой.

Я знаю, что вся структура данных немного запутанная и не идеальная. Я не прошу совета о том, как лучше структурировать мой код. Я работаю с большим количеством логики в данной структуре, и рефакторинг всего будет огромной болью.

Ответы [ 2 ]

0 голосов
/ 01 июля 2018

Logic не кажется подходящей сущностью для класса. Хотя дома кажутся правильными, но это не классы.

В JS OOP this обычно ссылается на экземпляр класса, как правило. Классы ouse могут упростить обработку отношений между домом и логикой, а экземпляр «логики» предоставляется путем внедрения зависимости:

class AbstractHouse {
  constructor(logic, name) {
    this.name = name;
    this.logic = logic;
  }
}

class RedHouse extends AbstractHouse {
  constructor(logic, name = 'Red House') {
    super(logic, name);
  }

  shouldAccess() {
    return this.isAccessible() && this.logic.allowedToEnter.redHouse()
  }
}

class Logic {
  ...
  houses = [new RedHouse(this)];
}

Тот факт, что базовый класс должен быть расширен для каждого типа дома для перечисления redHouse имени метода в явном виде в зависимости от типа дома, говорит о том, что это не идеальные отношения, и его можно улучшить, чтобы сделать его более гибким. Также неизвестно, сколько существует типов домов и целесообразно ли иметь класс для каждого типа.

Даже без фактического класса, дома могут следовать определенному интерфейсу, чтобы выставить «логический» экземпляр своим методам:

  houses = [
    {
      logic: this, // same as dependency injection in house constructor
      name: 'Red House',
      shouldAccess() {
        return this.isAccessible() && this.logic.allowedToEnter.redHouse()
      }
      ...
    }
  ];
0 голосов
/ 01 июля 2018

Структурирование моих мыслей и постановка вопроса помогли мне найти другое возможное решение.

Определение shouldAccess подобно следующему ...

shouldAccess__passLogic: function (logic) {
  return this.isAccessible() && logic.allowedToEnter.redHouse();
},

... и передача экземпляра класса этой функции при вызове функции (console.log(logic.houses[0].shouldAccess__Local(logic));) действительно решает проблему. Не очень красиво, но по крайней мере должно быть легко рефакторинг.

Я все еще открыт для других предложений!

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