2012-02-10 107 views
5

在PHP中,可以使用字符串來動態選擇實例化的類。這裏有兩個簡單的類在PHP中:來自動態函數名稱的Javascript新對象實例

<?php 
class Magic implements Genius { 
    public function perform() { 
    echo 'madya look :P' . PHP_EOL; 
    } 
} 

class Genie implements Genius { 
    public function perform() { 
    echo 'your wish has been granted!' . PHP_EOL; 
    } 
} 

現在有可能是一個變量,使得在運行時實例化的類是基於它的內容

$sGeniusClass = 'Magic'; 
$oGenius  = new $sGeniusClass(); 

現在在Javascript中,我喜歡使用的功能構造有類型的煩躁的一定程度上,在靜脈我可能有:

function Magic() {} 
Magic.prototype = { 
    perform : function() 
    { 
    console.log('madya look :P'); 
    } 
} 

function Genie() {} 
Genie.prototype = { 
    perform : function() 
    { 
    console.log('your wish has been granted!'); 
    } 
} 

我知道我可以拉過類似的東西到PHP​​與EVAL

方法#1

var sClassName = 'Genie'; 
eval('var oGenius = new ' + sClassName); 

我也看到an approach說對功能函數的調用:

方法2

var sClassName = 'Genie'; 
var oGenius = new Function('return new ' + sClassName)(); 

On the MDN雖然這聽起來像這樣的重新評估每一個實例被創建時遭受性能: 創建功能時與功能構造函數創建

函數對象進行解析。這比聲明一個 函數並在代碼中調用它的效率要低,因爲函數聲明 的函數與其餘代碼一起被解析。

現在我還有一個辦法,就是有點乏味:

方法3

var aClassMap = { 
    Magic : Magic, 
    Genie : Genie, 
    create : function(sClassName) { 
    if(this[sClassName] === undefined) 
     return false; 
    return new this[sClassName]; 
    } 
} 

var sClassName = 'Genie'; 
var oGenius = aClassMap.create(sClassName); 

這似乎是整個我的最愛,沒有用EVAL的,並沒有後續的重新評估,如解決方案#2。但它仍然有點工作,所以我的問題,雙重:

  1. 除了我已經顯示的3種方法之外,還有其他方法可以做到嗎?
  2. 有沒有類似於PHP的地方,一個字符串可以映射到一個函數被實例化?
+0

如何使用方法#2將參數傳遞給新函數? 所以它會被執行,如:'新的精靈('foo')''foo'也是一個變量? – 2013-06-28 20:47:30

+0

找到了!它是這樣的:'var oGenius = new Function('arg1','return new'+ sClassName +'(arg1)')($ argumentVariable);' – 2013-06-28 21:02:01

回答

4

我想你已經涵蓋了他們。您可以簡化您的第三個方法,但是,記住,全局變量和函數是window對象的屬性,所以你可以創建一個使用window全局類,像這樣:

var myClassName = "Genie"; 
window[myClassName] = function {}; 
window[myClassName].prototype = { 
    perform : function() 
    { 
    console.log('I am a ' + myClassName + ', and your wish has been granted!'); 
    } 
} 

我認爲表現會一樣好總是(因爲Javascript內部使用哈希表來引用對象屬性,不管是什麼)。

+0

絕對看起來像一個合理的方法,唯一的缺點是類可能不能移植到像_node.js_這樣的其他環境。但是,我沒有提到這個問題:) – quickshiftin 2012-02-10 03:23:25

+0

你實際上不必修改你聲明你的類型的方式。你仍然可以編寫函數Genie(){},然後用var o = new window [「Genie」]()創建一個實例。 – SynXsiS 2012-02-10 03:39:00

+0

啊@SynXsiS,這是一個很棒的提示,關於我見過的最乾淨的東西,thx。 – quickshiftin 2012-02-10 03:43:22