我公司允许我们在线编写javascript编辑器中的代码。其他库已预先加载,因此我们编写的代码可以访问这些库。
具体来说,我们可以在代码中使用Underscore.js和jQuery.js函数。我们也可以使用我们自己的库Graphie.js。
为了节省时间,我慢慢建立了自己的个人功能集,我将其复制并粘贴到我编写的每个代码中。这组函数现在已经很长了,我想从外部获取它(为了节省空间等)。
$.getScript( 'url/to/myfunctions.js' )
我尝试了上面的代码,但实在太好了。这个jQuery函数getScript
似乎将myfunctions作为自己的独立单元运行。这失败了,因为myfunctions使用我们的Graphie.js函数。
$.get( 'url/to/myfunctions', eval )
以上代码提取并成功eval
我的代码(我配置了我的服务器)。也太好了,不可能。我的代码中的任何jQuery和Underscode函数实际上都有效。但是我的代码中的任何Graphie函数都会导致错误。
答案 0 :(得分:3)
而不是
$.get( 'url/to/myfunctions', eval );
试
$.get( 'url/to/myfunctions', function(code) { eval(code); } );
这样,eval
函数将在与其余代码相同的范围内执行,而不是在jQuery的范围内。获取并执行代码后,您可以继续执行其余代码:
$.get( 'url/to/myfunctions', function(code) {
eval(code);
callback();
});
function callback() {
// Your code goes here
}
出于解释的目的,让我们使用这个简化的环境模型,在其中执行代码:
// JQuery is defined in the global scope
var $ = {
get: function( url, fn ) {
var responses = {
"url/to/myfunctions": "try {\
if(graphie) log('Graphie is visible.');\
} catch (e) {\
log('Graphie is not visible. (' + e + ')');\
}"
}; fn( responses[url] );
}
};
(function() {
// Graphie is defined in a local scope
var graphie = {};
(function() {
// Your code goes here
$.get( "url/to/myfunctions", eval );
$.get( "url/to/myfunctions", function(code) { eval (code); } );
})();
})();
The output: <ol id="output"></ol>
<script>
function log(msg) {
var el = document.createElement("li");
el.appendChild(document.createTextNode(msg));
output.appendChild(el);
}
</script>
如您所见,传递给$.get
的函数在其正文中执行。如果您只将eval
传递给$.get
,那么您不会捕获局部变量graphie
,这对于已评估的代码是不可见的。通过将eval
包装在匿名函数中,可以捕获对局部变量graphie
的引用,然后对已计算的代码可见。
答案 1 :(得分:0)
我建议不要使用eval
。但是,您可以遵循以下模型。
首先在myFunctions.js
中,将所有代码包装到一个函数中。
(function(_, $, graphie) {
// declare all your functions here which makes use of the paramters
}) // we will be calling this anonymous function later with parameters
然后在获得脚本之后你就可以了
$.get( 'url/to/myfunctions', function(fn){
var el = document.createElement('script');
el.type = 'text/javascript';
el.text = fn + '(_, jQuery, Graphie);';
document.head.appendChild(el);
});
请注意,我已将Graphie
作为参数,但我不确定。所以在那里放置正确的graphie变量。
答案 2 :(得分:0)
假设您对此脚本具有ajax访问权限(因为这是$ .get在您显示的示例代码中所做的事情),您可以尝试使用jQuery&#39; .html()
来放置脚本使用页面的可变环境执行它。
$.ajax({
url: 'url/to/myfunctions.js',
type: 'GET',
success: function (result) {
var script = '<scr'+'ipt>'+result+'</scr'+'ipt>';
var div = $("<div>");
$("body").append(div);
div.html(script);
}
});
在内部,此脚本最终将由jQuery的globalEval
函数执行。 https://github.com/jquery/jquery/blob/1.9.1/src/core.js#L577
// Evaluates a script in a global context
// Workarounds based on findings by Jim Driscoll
// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
globalEval: function( data ) {
if ( data && jQuery.trim( data ) ) {
// We use execScript on Internet Explorer
// We use an anonymous function so that context is window
// rather than jQuery in Firefox
( window.execScript || function( data ) {
window[ "eval" ].call( window, data );
} )( data );
}
}
我还在这里问了一个与此相关的问题:Why is it that script will run from using jquery's html but not from using innerHTML?
答案 3 :(得分:0)
感谢大家的帮助,以下是有效的解决方案......
myfunctions.js
文件必须包含在函数中:
function everything(_,$,Graphie){
// every one of myfunctions now must be attached to the Graphie object like this:
Graphie.oneOfMyFunctions = function(input1,input2,etc){
// content of oneOfMyFunctions
}
// the rest of myfunctions, etc.
}
然后在我的代码中我可以使用:
检索它$.get( '//path/to/myfunctions', eval )
everything(_,jQuery,mygraphievar);
不知何故,eval
编码的代码无法访问全局变量mygraphievar
,这就是为什么它必须传入而不是eval
的一部分ed代码(这里Amit犯了一个小错误)。
此外,everything
函数在$.get()
的外部执行,以便在执行以下任何其他代码之前对mygraphievar
进行更改。
应该注意$.get()
实际上是一个异步函数,在执行其他代码之前不会调用eval
。这导致代码在我第一次运行时失败,但在第一次将函数保存在内存中然后一切正常。正确的解决方案是在$.get()
的回调函数中编写我想要执行的所有代码,但我很懒。
还应该知道$.getScript()
可以使用稍微简单的解决方案,但我没有时间对其进行验证。