-1

我正在尝试将一个名称空间的内容转储到 javascript 中的另一个名称空间中。我可以直接做到这一点的唯一方法如下:

var CHESSMEN = {

  Chariot: function(color) {
    return {
      color: color,
      abbreviation: 'R',
      type: 'Chariot'
    };
  },

  Horse: function(color) {
    return {
      color: color,
      abbreviation: 'H',
      type: 'Horse'
    };
  },

  Elephant: function(color) {
    return {
      color: color,
      abbreviation: 'E',
      type: 'Elephant'
    };
  },

  Advisor: function(color) {
    return {
      color: color,
      abbreviation: 'A',
      type: 'Advisor'
    };
  },

  General: function(color) {
    return {
      color: color,
      abbreviation: 'G',
      type: 'General'
    };
  },

  Cannon: function(color) {
    return {
      color: color,
      abbreviation: 'C',
      type: 'Cannon'
    };
  },

  Soldier: function(color) {
    return {
      color: color,
      abbreviation: 'S',
      type: 'Soldier'
    };
  }
}
Object.freeze(CHESSMEN)

function Game(board) {

  for (var piece in CHESSMEN) {
    eval('var ' + piece + ' = CHESSMEN.' + piece);
  }

  if (typeof(board) === 'undefined') {
    var board = {
      a1: new Chariot('red'),
      b1: new Horse('red'),
      c1: new Elephant('red'),
      d1: new Advisor('red'),
      e1: new General('red'),
      f1: new Advisor('red'),
      g1: new Elephant('red'),
      h1: new Horse('red'),
      i1: new Chariot('red'),
      b3: new Cannon('red'),
      h3: new Cannon('red'),
      a4: new Soldier('red'),
      c4: new Soldier('red'),
      e4: new Soldier('red'),
      g4: new Soldier('red'),
      i4: new Soldier('red'),
      a10: new Chariot('black'),
      b10: new Horse('black'),
      c10: new Elephant('black'),
      d10: new Advisor('black'),
      e10: new General('black'),
      f10: new Advisor('black'),
      g10: new Elephant('black'),
      h10: new Horse('black'),
      i10: new Chariot('black'),
      b8: new Cannon('black'),
      h8: new Cannon('black'),
      a7: new Soldier('black'),
      c7: new Soldier('black'),
      e7: new Soldier('black'),
      g7: new Soldier('black'),
      i7: new Soldier('black')
    };
  }

  // et cetera
}

在这里,我使用for in循环来遍历冻结对象的eval键,并将这些键及其关联值转储到Game构造函数的范围内。许多人告诉我不要使用eval,但我没有看到直接合并命名空间的另一种方法。这不安全吗?将棋子构造函数称为CHESSMEN对象的属性对我来说会更好吗?

4

2 回答 2

2

正如@zerkms 指出的那样,您应该使用CHESSMEN.Chariotetc 访问它们:

var board = {
  a1: new CHESSMAN.Chariot('red'),
  b1: new CHESSMAN.Horse('red'),
  c1: new CHESSMAN.Elephant('red'),
  //etc.

此外,Chariot如果您打算使用new. 你想要的模式是:

  Chariot: function(color) {
    this.color = color;
    this.abbreviation = 'R';
    this.type = 'Chariot'
  },

否则,当您调用时new,将返回的将是您正在创建的对象文字,而不是Chariot您可能想要的实例。如果您真正需要的只是您返回的值,那么您可以编写代码而无需new

var board = {
  a1: CHESSMAN.Chariot('red'),
  b1: CHESSMAN.Horse('red'),
  c1: CHESSMAN.Elephant('red'),
  //etc.
于 2013-07-08T00:00:57.077 回答
1

这是可能的,但非常不鼓励并且在严格模式下是不可能的。

with (CHESSMEN) {
    // Now CHESSMEN's properties are available without saying "CHESSMEN.whatever"
    console.log(Chariot === CHESSMEN.Chariot); // logs "true"
}

我重申:这是个坏主意。很难分辨任何标识符指的是什么,它可能运行得更慢,而且它不向前兼容。有关更多详细信息,请参阅MDN

至于 eval 的安全性:如果在稍后的某个时间点,您的代码以CHESSMEN具有用户定义属性的方式发生更改,攻击者可能会命名一个属性foo; doHorriblyEvilThing();以导致您的代码做一些可怕的坏事。

于 2013-07-08T00:02:17.373 回答