ES6:在同一函数中访问两个不同的作用域(类全局和对象本地)

时间:2018-07-01 19:03:07

标签: javascript ecmascript-6 scope

这很难解释。请原谅这个牵强的例子。

我想在同一函数中访问两个不同的作用域(类全局和对象本地)。所述功能是一种对象方法。

我正在使用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 :(得分:1)

Logic似乎不是一个类的适当实体。尽管房屋似乎是适当的实体,但它们不是阶级。

在JS OOP中,根据经验,this通常是指类实例。 Рouses类将使处理内部逻辑关系更加容易,并且通过依赖注入提供了“逻辑”实例:

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()
      }
      ...
    }
  ];

答案 1 :(得分:0)

整理我的想法并提出问题可以帮助我提出另一个可能的解决方案。

定义$factory->define(App\Category::class, function (Faker $faker) { static $counter = 1; $locales = Language::pluck('lang'); $titles = array('slug' => 'CATEGORY-'.$counter); foreach ($locales as $locale) { $titles[$locale] = [ 'title' => 'Title for category-' .$counter. ' on '. $locale . ' language' ]; } $counter++; return $titles; }); 如下...

shouldAccess

...并在函数调用(shouldAccess__passLogic: function (logic) { return this.isAccessible() && logic.allowedToEnter.redHouse(); }, )上将类实例传递给该函数确实可以解决该问题。不是很漂亮,但至少应该易于重构。

尽管如此,我仍然愿意接受其他建议!