我有一个 JavaScript 函数,它在对象上挖掘并为函数对象创建一个字符串值。有这个 JSON:
{
"active": true,
"icons": {
"activeHeader": "ui-icon-alert"
},
"animate": {
"duration": 1000, "always": "dMethod"
}
}
我JSON.parse
在这个字符串上使用,所以我options.animate.always
作为一个string
带有值的值dMethdod
,它实际上是方法的名称。所以我可以通过它访问它window[options.animate.always]
,我希望将 options.animate.always 从字符串更改为指向字符串的方法。我为这项工作制作了一个功能:
function SetFunctions(options, functionName) {
var path = functionName.split(".");
var setterObject = options;
for (var k = 0; k < path.length; k++) {
if (setterObject != undefined) {
setterObject = setterObject[path[k]];
} else {
break;
}
}
if (setterObject != undefined && window[setterObject] != undefined) {
setterObject = window[setterObject];
}
}
我使用从解析返回的变量和函数名称animate.always
作为值来调用此函数。找到正确属性的部分有效,但是当我设置setterObject
更改的值时不会影响原始值。
我正在考虑将引用构建为字符串'options.animate.always = dMethod'
并eval
在其上使用,但我真的想避免使用 eval 函数(我知道 eval 是邪恶的:))。
最终解决方案:
我将答案放在一起并完成了我的方法。最后变成了两种方法。我评论它并分享可能对其他人有用:
function ChangeStringToFunction(functionPath, rootObject, separator) {
// functionPath is required parameter
if (functionPath === undefined || functionPath === null) return;
// rootObject is optional. If not supplied the window object will be the base of the search
var localRootObject = rootObject === undefined ? window : rootObject;
// separator is optional. If not supplied the '.' will be the separator
var localSeparator = separator === undefined ? "." : separator;
// split the string reference (example "jui.someObj1.someOjb2"
var pathParts = functionPath.split(localSeparator);
var currentObject = localRootObject;
// exclude the last part
for (var i = 0; i < pathParts.length - 1; i++) {
currentObject = currentObject[pathParts[i]];
// it's useless to go forward if there is no object
if (currentObject === undefined) return;
}
// get the string represent the name of the function (full path could be included)
var currentValue = currentObject[pathParts[pathParts.length - 1]];
// the value must be a string
if (typeof currentValue !== "string") return;
// get the function reference based on the value provided
var functionReference = ResolveFunction(currentValue);
// if the result is not a function it's meaningless to continue
if (typeof functionReference !== "function") return;
// and finally change the string value of the object with the function value represent by our string
currentObject[pathParts[pathParts.length - 1]] = functionReference;
}
function ResolveFunction(functionPath, separator, rootObject) {
if (functionPath === undefined || functionPath === null) return undefined;
var localRootObject = rootObject === undefined ? window : rootObject;
var localSeparator = separator === undefined ? "." : separator;
var pathParts = functionPath.split(localSeparator);
var currentObject = localRootObject;
for (var i = 0; i < pathParts.length; i++) {
currentObject = currentObject[pathParts[i]];
if (currentObject === undefined) break;
}
return typeof currentObject === "function" ? currentObject : undefined;
}