对于我的函数检查算法,是否有比 eval() 更好的替代方法
Is there a better alternative to eval() for my function checking algorithm
我有以下代码旨在随时检查函数是否存在。 此代码目前没有任何错误。我使用它是因为我的 javascript 文件以任意顺序加载,并且对于我的项目来说是必要的,它是这样完成的。由于我的 javascript 文件是分开的,以便 运行 在它们之间运行函数,因此您必须将它们存储在全局变量中,然后从全局变量中调用该函数。
Javascript 文件示例:"checker.js" // 检查函数是否存在!
var funcList = {};
$(document).ready(function(){
funcList.requireJS =
function requireJS(requires,callback){
console.log("requireJS Starting With Requires Below:");
console.log(requires);
var attempts = 0;
attemptRequire();
function attemptRequire(){
$.each(requires, function (key, value){
attempts++;
console.log("Checking:"+value+" attempts="+attempts);
if (typeof eval(value) !== 'undefined'){
callback(); //them run the function
}else{
console.log("require JS waiting...");
setTimeout(function(){attemptRequire();}, 100);//wait and try again every 100 milliseconds.
}
});
}
console.log("requireJS Finished!...");
};
});
使用全局函数的例子:sample.js
$(document).ready(function(){
console.log("Quote.Js Loading...");
requires = {
0 : "$.fn.mask"
};
funcList["requireJS"](requires, function(){
$("#partone_phone").mask("(999) 999-9999? x99999");
console.log("Quote.Js Loaded!");
});
});
想法是,如果 jQuery 上 'masking' 的插件尚未加载,那么它不会尝试 运行 代码,但一旦加载它就会。在未加载插件时尝试 运行 .mask 将导致字段不具有所需的影响。我以 jquery.mask 为例,但这适用于任何事物。
但是我正在使用 jquery.mask,因为作为 jquery 函数,似乎 唯一引用它的方法是 $.fn.mask
通常我可以通过说 typeof functionNameHere !== 'undefined'
来测试函数,这有效,但是因为如果我发送字符串 '$. fn.mask' 除非我在它周围放置一个 eval() ,否则它不起作用......众所周知,这是错误的形式!
有没有人有更好的替代方法来使用 eval() 来完成这项工作?
另请注意:
requires = {
0 : $.fn.mask
};
尝试在没有字符串的情况下直接发送函数是行不通的,因为如果它是未定义的,它在进入 requireJS 时仍保持未定义状态。
一个很好的替代方法是在使用之前定义函数。
例如:
function foo() {}
foo()
如果您正在加载脚本,请确保定义插件的标签位于使用它的标签之上:
<script src="/yet/another/jquery/plugin.js"></script>
<script src="/my/code.js"></script>
能不能只传递函数本身?
由于您正在 eval
传递的名称,这些函数在全局范围内,您对调用它们的上下文几乎没有兴趣。
与其传递名称并假设它们可以访问,不如传递对函数的引用并调用它。它将使您的设计更加更加灵活。
requires = {
0 : $.fn.mask
};
和
if (value() !== 'undefined') {
callback(); //them run the function
如果您需要控制函数的执行上下文,请在传入它们之前使用bind
:
requires = {
0: $.fn.mask.bind($),
1: console.log.bind(console)
};
bind
method 允许您准备具有给定作用域和一些参数的函数。
更好的选择可能是只传递一个要执行的函数,而不是 returns 您正在寻找的方法或 false。
requires = {
0 : function () {
return $ && $.fn && $.fn.mask;
}
};
现在,您所要做的就是调用 requires[0]()
以查看是否定义了 $.fn.mask
。
旁注:将此引用为 "requireJS" 可能会让未来的开发人员感到困惑,因为这不是 requireJS,它只是您自己的函数,用于检查脚本是否已完成加载。 requireJS 是一个模块加载器,如果您使用它可能会减少这个问题。
好的,最近我接受的答案产生了很多随机的 javascript 错误,这些错误会发生并且它们不会向控制台报告错误。
我做了一个新算法,它看起来更可靠,但仍然依赖于 eval()...,但至少它有效。
我并不是说这是一个好的答案,但它对我有用,也许对其他人也有用。
var funcList = {};
$(document).ready(function(){
//Because javascript files are loaded asynchronously, use requireJS to ensure javascript is loaded...
//...for your modules to prevent errors. To load this function from anyfile use the funcList global var.
//Helper function to get REAL type since mobile safari has issues
var toType = function(obj) {
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
funcList.requireJS =
function requireJS(requires,callback){
console.log("requireJS Starting With Requires Below****:");
console.log(requires);
var attempts = 0;
var successcount = 0;
attemptRequire();
function attemptRequire(){
successcount = 0;//reset it to 0
$.each(requires, function (key, value){
attempts++;
console.log("Checking*:"+value+" attempts="+attempts);
var type = '';
var errorOccured = false;
try{
console.log("trying...");
type = toType(eval(value));
console.log("type="+type);
if(type=="function"){
successcount++;
attempts--;
errorOccured = false;
}else{
console.log("throwing...");
throw "Custom error message: Function is undefined, must be defined as function";
}
}
catch (err){
errorOccured = true;
console.log("catching...");
console.log("error="+err.message);
}
finally {
if(errorOccured == true){
console.log("JS For "+value+" Not Ready Yet, Trying Again in 100ms");
setTimeout(function(){attemptRequire();}, 100);//wait and try again every 100 milliseconds.
return false;//exit the entire foreach loop early~
}
}
});
//Only call the callback once if all requires came in correctly.
if(successcount == Object.keys(requires).length){
console.log("calling callback...");
callback(); //then run the function
}
}
console.log("End of requireJS Function Call");
};
console.log("includes.js loaded");
});
如果需要,请修改其中的 console.log,它应该可以使用了。在这里调用它是下面的示例。
$(document).ready(function(){
requires = {
0 : '$.fn.mask',
1 : '$.fn.validate',
2 : 'google.maps.LatLng'
};
funcList["requireJS"](requires, function(){
//code dependent upon mask and validate here!
});
});
我有以下代码旨在随时检查函数是否存在。 此代码目前没有任何错误。我使用它是因为我的 javascript 文件以任意顺序加载,并且对于我的项目来说是必要的,它是这样完成的。由于我的 javascript 文件是分开的,以便 运行 在它们之间运行函数,因此您必须将它们存储在全局变量中,然后从全局变量中调用该函数。
Javascript 文件示例:"checker.js" // 检查函数是否存在!
var funcList = {};
$(document).ready(function(){
funcList.requireJS =
function requireJS(requires,callback){
console.log("requireJS Starting With Requires Below:");
console.log(requires);
var attempts = 0;
attemptRequire();
function attemptRequire(){
$.each(requires, function (key, value){
attempts++;
console.log("Checking:"+value+" attempts="+attempts);
if (typeof eval(value) !== 'undefined'){
callback(); //them run the function
}else{
console.log("require JS waiting...");
setTimeout(function(){attemptRequire();}, 100);//wait and try again every 100 milliseconds.
}
});
}
console.log("requireJS Finished!...");
};
});
使用全局函数的例子:sample.js
$(document).ready(function(){
console.log("Quote.Js Loading...");
requires = {
0 : "$.fn.mask"
};
funcList["requireJS"](requires, function(){
$("#partone_phone").mask("(999) 999-9999? x99999");
console.log("Quote.Js Loaded!");
});
});
想法是,如果 jQuery 上 'masking' 的插件尚未加载,那么它不会尝试 运行 代码,但一旦加载它就会。在未加载插件时尝试 运行 .mask 将导致字段不具有所需的影响。我以 jquery.mask 为例,但这适用于任何事物。
但是我正在使用 jquery.mask,因为作为 jquery 函数,似乎 唯一引用它的方法是 $.fn.mask
通常我可以通过说 typeof functionNameHere !== 'undefined'
来测试函数,这有效,但是因为如果我发送字符串 '$. fn.mask' 除非我在它周围放置一个 eval() ,否则它不起作用......众所周知,这是错误的形式!
有没有人有更好的替代方法来使用 eval() 来完成这项工作?
另请注意:
requires = {
0 : $.fn.mask
};
尝试在没有字符串的情况下直接发送函数是行不通的,因为如果它是未定义的,它在进入 requireJS 时仍保持未定义状态。
一个很好的替代方法是在使用之前定义函数。
例如:
function foo() {}
foo()
如果您正在加载脚本,请确保定义插件的标签位于使用它的标签之上:
<script src="/yet/another/jquery/plugin.js"></script>
<script src="/my/code.js"></script>
能不能只传递函数本身?
由于您正在 eval
传递的名称,这些函数在全局范围内,您对调用它们的上下文几乎没有兴趣。
与其传递名称并假设它们可以访问,不如传递对函数的引用并调用它。它将使您的设计更加更加灵活。
requires = {
0 : $.fn.mask
};
和
if (value() !== 'undefined') {
callback(); //them run the function
如果您需要控制函数的执行上下文,请在传入它们之前使用bind
:
requires = {
0: $.fn.mask.bind($),
1: console.log.bind(console)
};
bind
method 允许您准备具有给定作用域和一些参数的函数。
更好的选择可能是只传递一个要执行的函数,而不是 returns 您正在寻找的方法或 false。
requires = {
0 : function () {
return $ && $.fn && $.fn.mask;
}
};
现在,您所要做的就是调用 requires[0]()
以查看是否定义了 $.fn.mask
。
旁注:将此引用为 "requireJS" 可能会让未来的开发人员感到困惑,因为这不是 requireJS,它只是您自己的函数,用于检查脚本是否已完成加载。 requireJS 是一个模块加载器,如果您使用它可能会减少这个问题。
好的,最近我接受的答案产生了很多随机的 javascript 错误,这些错误会发生并且它们不会向控制台报告错误。
我做了一个新算法,它看起来更可靠,但仍然依赖于 eval()...,但至少它有效。
我并不是说这是一个好的答案,但它对我有用,也许对其他人也有用。
var funcList = {};
$(document).ready(function(){
//Because javascript files are loaded asynchronously, use requireJS to ensure javascript is loaded...
//...for your modules to prevent errors. To load this function from anyfile use the funcList global var.
//Helper function to get REAL type since mobile safari has issues
var toType = function(obj) {
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
funcList.requireJS =
function requireJS(requires,callback){
console.log("requireJS Starting With Requires Below****:");
console.log(requires);
var attempts = 0;
var successcount = 0;
attemptRequire();
function attemptRequire(){
successcount = 0;//reset it to 0
$.each(requires, function (key, value){
attempts++;
console.log("Checking*:"+value+" attempts="+attempts);
var type = '';
var errorOccured = false;
try{
console.log("trying...");
type = toType(eval(value));
console.log("type="+type);
if(type=="function"){
successcount++;
attempts--;
errorOccured = false;
}else{
console.log("throwing...");
throw "Custom error message: Function is undefined, must be defined as function";
}
}
catch (err){
errorOccured = true;
console.log("catching...");
console.log("error="+err.message);
}
finally {
if(errorOccured == true){
console.log("JS For "+value+" Not Ready Yet, Trying Again in 100ms");
setTimeout(function(){attemptRequire();}, 100);//wait and try again every 100 milliseconds.
return false;//exit the entire foreach loop early~
}
}
});
//Only call the callback once if all requires came in correctly.
if(successcount == Object.keys(requires).length){
console.log("calling callback...");
callback(); //then run the function
}
}
console.log("End of requireJS Function Call");
};
console.log("includes.js loaded");
});
如果需要,请修改其中的 console.log,它应该可以使用了。在这里调用它是下面的示例。
$(document).ready(function(){
requires = {
0 : '$.fn.mask',
1 : '$.fn.validate',
2 : 'google.maps.LatLng'
};
funcList["requireJS"](requires, function(){
//code dependent upon mask and validate here!
});
});