可以从javascript文件中提取函数吗?

时间:2012-03-06 17:54:16

标签: javascript

不确定这是否是正确的方法,如果这甚至是一个“好”的问题,但我正在加载javscript作为插件样式架构的一部分,我有以下问题:

如果某个特定节点有插件引用,我想根据该插件的json描述提供的url加载该插件。描述将具有类似以下内容(或功能等同物):

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

当javascript加载时,我将有一个onload处理程序,它将检查窗口对象上是否存在函数名称,如果存在,则创建该函数的新实例并将其传递给配置数据(或多或少) ),这部分非常有效,只有少数例外。

有时候我没有引用我需要调用的函数的名称,也没有办法从json中获取它。什么是理想的,如果我可以告诉哪个函数被添加到脚本的onload回调上的window对象并创建该函数的实例。这可能吗?我只需要担心现代浏览器,特别是webkit。如果问题不清楚,我很乐意澄清,但是制作一个小提琴可能很困难,因为要编写很多代码来达到最小的例子。

我到目前为止所考虑的是在加载的脚本文件中创建某种全局变量,如

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

只是在加载脚本时创建一个LoadedClass实例,但这并不是灵丹妙药,因为我不会一直在编写插件。

编辑:这些脚本很可能不是来自同一个域。

2 个答案:

答案 0 :(得分:2)

您尚未指定加载脚本文件的方式。我希望你能在onload handler中获得脚本文本。

无论如何,我正在使用jQuery.getScript解释如何执行此操作。在此,您将获得成功处理程序中的脚本文本data。所以你可以使用它来获取加载的函数。

假设脚本文件 dynamic.js 包含

function MediaAnalytics(){};

使用getScript

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

此处NewFunctionMediaAnalytics。 这将是脚本的第二次执行,因为getScript在执行成功处理程序并将其添加到窗口对象后调用成功处理程序。您可以new NewFunction()实例化。

如果您不喜欢使用eval,另一种方法是使用RegEx查找函数的名称

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

这将提醒功能MediaAnalytics(match返回一个数组。可以从中检索该函数的名称。

您可以使用更好的RegExp来提取确切的函数名称并获取window对象的属性。

编辑:(没有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

答案 1 :(得分: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')