我试图在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
对象的属性会不会更好?
答案 0 :(得分:2)
正如@zerkms指出的那样,你应该使用CHESSMEN.Chariot
等来访问它们:
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.
答案 1 :(得分: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();
命名为你的代码做了可怕的恶事。