2013-07-07 57 views
-1

我想將一個命名空間的內容轉儲到另一個javascript中。我能想出直接做到這一點的唯一方法是如下:使用eval在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對象的屬性,將我稱爲棋子構造函數會更好嗎?

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

而且,你幾乎肯定不希望自己的Chariot實現你擁有它,如果你打算使用new方式:

+3

爲什麼你需要*導入*他們?爲什麼不只是使用'CHESSMEN.Chariot'等? – zerkms

+0

我想知道是否有任何_disadvantage_導入它們。但是爲了解決你的問題,我沒有理由在'CHESSMEN.Chariot'上使用'Chariot'。我只是好奇這個配方是否不安全。 – HandyAndyShortStack

+2

是的 - 你正在做一些解決任務所不需要的東西。你的每一步都應該由一些要求引起。相反 - 當你做了一些奇怪的事情,並將它們證明爲「爲什麼不」時 - 並非如此。 – zerkms

回答

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();來讓你的代碼做一些可怕的惡事。

+0

謝謝。我想我只需要習慣於將單獨的命名空間保存在我的javascript中。我特別感謝你的意見,即使沒有當前的安全問題,在將來修改代碼時,我也必須時刻擔心安全問題。 – HandyAndyShortStack

+0

@HandyAndyShortStack:安全性是什麼?你在保護自己嗎? – zerkms

2

由於@zerkms指出,你應該使用CHESSMEN.Chariot等訪問它們。你想要的模式是:

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.