0

我有一个 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;
}
4

2 回答 2

1

但是当我设置 setterObject 的值时,更改不会影响原始值。

是的,您只是分配给一个变量。除了变量之外,这永远不会改变其他任何东西,因为 JavaScript 没有指针。

要更改对象,您必须分配给属性。在您的情况下,您将不得不省略最后一次迭代以获取然后分配给的对象:

function SetFunctions(options, functionName) {
    var path = functionName.split("."),
        setterObject = options;
    for (var k=0; setterObject!=null && k<path.length-1; k++) {
        setterObject = setterObject[path[k]];
    }
    var prop = path[k],
        fn = setterObject!=null && window[setterObject[prop]];
    if (fn) {
        setterObject[prop] = fn;
    }
}

顺便说一句,我认为在您的情况下,构建一个使用存储在该属性中的名称直接调用函数的函数可能更容易CallFunctions,而不是用方法替换属性值 - 除非您打算经常调用它。

于 2013-08-12T14:54:45.257 回答
0

这取决于您想要的间接级别。

如果该方法将始终称为“始终”,您可以执行以下操作:

function SetFunction(object, propertyName,  functionName) {
    var functionObj = window[functionName];
    object[propertyName] = functionObj;
}

并这样称呼它:

SetFunction(myObj.animate, "always", myObj.animate.always);

但我怀疑你想要更通用的东西?

于 2013-08-12T15:39:13.973 回答