2012-03-06 21 views
3

不知道這是否是正確的方法,如果這甚至是一個「好」的問題,但我正在加載一個javscript作爲插件樣式體系結構的一部分,並且存在以下問題:可能從javascript文件中提取函數嗎?

如果某個特定節點具有對插件的引用,我想要通過該插件的json描述提供的每個url加載該插件。說明將有類似於下面的東西(或其功能等價):

{ 
    "pluginSrc" : "http://mysite.com/plugins/1204.js", 
    "configData" : 
    { 
     "someData", "someValue", 
     "someMoreData", "etc" 
    } 
} 

當JavaScript的負荷,我將有一個onload處理,將檢查,看是否有函數名稱的窗口對象,如果存在因此,創建該函數的一個新實例並將它傳遞給配置數據(或多或少),這部分工作得很好,只有一些例外。

有時我沒有引用我需要調用的函數的名稱,並且無法從json中獲取它。最理想的是,如果我可以知道在腳本的onload回調中將哪個函數添加到窗口對象並創建該函數的實例。這可能嗎?我只需要擔心現代瀏覽器,尤其是webkit。如果問題不明確,我會很高興澄清,但抱歉,製作小提琴可能會很困難,因爲需要編寫大量代碼才能實現最小范例。

我正想着到目前爲止是創造某種全局變量在加載腳本文件中像

function MediaAnalytics(){}; 
var LoadedClass = MediaAnalytics; 

和腳本加載時剛剛創造LoadedClass的實例,但是這屬於短因爲我不會一直在寫這個插件。

編輯:這些腳本很可能不會來自同一個域。

+0

如果您製作了一個空白的iframe,在那裏加載JS,然後將iframe的'window'中的函數複製到主窗口? (我不知道這是否有效,只是把它扔在那裏) – 2012-03-06 18:42:58

+1

有趣的想法,它可能在很多情況下工作。不幸的是,這個項目通過手機輸出到Android/iPhone,iframe可能會導致我想避免的各種問題。偉大的建議,但! – Shane 2012-03-06 18:57:50

回答

2

您尚未指定如何加載腳本文件。我希望你能在onload handler中獲得腳本文本。

無論如何,我解釋如何使用jQuery.getScript來做到這一點。在這裏,您將獲得成功處理程序中的腳本文本,如data。所以你可以用它來獲得加載的函數。

假設腳本文件是動態的。JS包含它使用getScript

$.getScript("dynamic.js", function (data, textStatus, jqxhr) { 
    var NewFunction; 
    eval("NewFunction = " + data); 
    alert(NewFunction.name); // here you will get alert showing MediaAnalytics 
}); 

這裏NewFunctionMediaAnalytics

function MediaAnalytics(){}; 

負荷。 這將是腳本的第二次執行,因爲getScript在執行成功處理程序並將其添加到窗口對象後調用成功處理程序。你可以給new NewFunction()實例化。

如果你不喜歡使用eval,另一種方法是使用正則表達式查找功能

$.getScript("dynamic.js", function (data, textStatus, jqxhr) { 
    alert(data.match(/function(.*)\(/)); 
}); 

這將提醒功能MediaAnalytics(的名稱。match返回一個數組。名稱該功能可以從中檢索。

您可以使用一個更好的正則表達式提取確切的函數名稱和獲取窗口對象的屬性。

編輯:(無jquery)

或者你可以加載你的腳本作爲文本,並添加到窗口作爲腳本標記在你的onload處理程序。即使插件腳本不是你的,你也可以使用你的技巧。

var dynamicjs = "function MediaAnalytics(){};"; // script loaded as text 

var modified = "LoadedClass = " + dynamicjs; 

var head= document.getElementsByTagName('head')[0]; 
var script= document.createElement('script'); 
script.type= 'text/javascript'; 
script.textContent= modified; // innerText in some browsers 
head.appendChild(script); 

alert(LoadedClass); // LoadedClass is MediaAnalytics 
+0

輝煌。現在就去嘗試。我不想過分關注加載方法,因爲我在那裏有一些靈活性。 – Shane 2012-03-06 21:31:55

+0

我在http嗅探器中看到了一個響應,但「數據」正在追蹤未定義。 http://jsfiddle.net/hyperthalamus/x274C/任何想法,爲什麼這可能是? – Shane 2012-03-06 22:00:44

+0

這應該是一個很好的方式來做到這一點 – 2012-03-06 22:10:17

1

我會建議讓它在json中有入口函數的名字。在我看來,這將是最簡單的方法。

但是,你可以嘗試的東西是迭代window的所有屬性。如果在加載腳本後在window中發現了新函數,則可以假設這是剛加載的那個函數。

事情是這樣的..

var windowMembers = []; 
function loadScript() { 
    for(var m in window) { 
     windowMembers.push(m); 
    } 

    //load your new script 
    //some code here to load the script 

    //put an onload handler... 
    s.onload = function() { 
     for(var m in window) { 
      if(windowMembers.indexOf(m) == -1) { 
       //window[m] was added after the script loading began 
       //call it: 
       window[m]('blah blah'); 
      } 
     } 
    } 
} 

爲了安全起見,你可以任意檢查新的屬性是一個函數,例如。

if(typeof window[m] == 'function') 
+0

我認爲這是迄今爲止我所見過的最接近的事情。有什麼樣的回調,你可以添加到「S」,將在腳本加載之前執行?我遇到的一個問題是這是一個龐大的代碼庫,插件來自誰知道在哪裏,我很確定有其他組件或插件可以創建窗口級別的功能。如果在腳本被實例化之前我有某種捕獲方式,我認爲這是可行的。 – Shane 2012-03-06 19:22:54

+0

如果插件覆蓋了另一個插件的功能,該怎麼辦? – 2012-03-06 19:41:35

+0

我認爲不能創建該類的新實例。不知道它會對現有實例做什麼。儘管可能,但考慮到環境,這種情況不太可能發生,如果確實如此,操作中的某個人可能會失去4-5個小時來查明問題。 :) – Shane 2012-03-06 19:49:20

相關問題