如何在另一个函数中定义的函数在窗口范围内?

时间:2017-01-20 17:44:20

标签: javascript jquery

我正在为一些任意代码创建一个包装器(让我们称之为托管代码)。托管代码可能包含一些在窗口范围内定义的功能,并且是页面上其他脚本所期望的(可怕的,1997,实践,我知道,但这是我必须处理的),作为全局函数。

包装器的目的是延迟执行包装代码,直到加载jQuery。它看起来像这样:

(function () {
    var once = true,
    check = setInterval(function () {
        if (window.$ && once) {
            once = false; // setInterval can stack up if the UI freezes. Ensure this only gets called once.

            executeBundle();

            clearInterval(check);

            console.log('Jquery loaded');
        }
    }, 100);
})()

// Wrapper proper
function executeBundle() {
  // oodles of code of any origin
}

既然托管代码已经包含在executeBundle函数中,那么在其中声明的所有函数/变量都将作用于该函数。对于托管代码本身而言,这不是一个问题,但对于可能依赖于它提供的全局函数的其他单独加载的脚本。

我想知道是否有人知道像eval这样的策略,但没有安全问题,这可能会让我保留运行托管代码的窗口范围。限制是我根本无法修改托管代码 - 只是包装器。

2 个答案:

答案 0 :(得分:2)

基于T.J. Crowder的惊人答案,我意识到我可以将托管代码添加到<script>元素并将其添加到<head>,如下所示:

var codeBundle = // Code in one long string

function evaluateBundle() {
    var script = $('<script type="text/javascript"/>')

    script.html(codeBundle);

    $('head').append(script);
}

让解析器评估代码。

答案 1 :(得分:1)

  

我想知道是否有人知道像eval这样的策略,但没有安全问题

如果你自己编写eval自己的代码,那么无论如何都要将它放在script代码中,那么就没有任何安全问题。您以任何一种方式运行代码。

如果您正在包装的代码将直接显示在evaluateBundle中并且它具有应该位于的声明(var和函数声明),则您无法执行此操作全球范围。处理那些需要修改包装代码。

如果您单独加载该代码,可以执行此操作,然后对其执行全局评估。例如,将它放在一个非JavaScript类型的脚本块中,这样浏览器就不会执行它:

<script type="x-code-to-wrap"></script>

......然后:

function evaluateBundle() {
    var code = document.querySelector('script[type="x-code-to-wrap"]').textContent;
    (0, eval)(code);
}

(0, eval)(code)位是全局evalmore on MDN)。

您可能需要调整textContent部分,以实现跨浏览器兼容性。 This question's answers建议使用jQuery&#39; html函数:

function evaluateBundle() {
    (0, eval)($('script[type="x-code-to-wrap"]').html());
}

Live example on JSBin