如何确定是否定义了JavaScript函数?

时间:2012-05-04 12:53:49

标签: javascript

我想检查函数是否已定义(我不在乎,我的意思是它是可调用的)

示例代码:

var functions = {
    'alert':'alert',
    'undefinedFunction':'undefinedFunction',
    'ff.showAlert':'ff.showAlert'
};

var ff = {
    showAlert: function() {
        alert('the function works');
    }
};

for (i in functions) {
    console.log(i+' : '+typeof window[functions [i]]);
}

返回:

alert : function
undefinedFunction : undefined
ff.showAlert : undefined

console.log(typeof window.ff.showAlert); return function

Live demo
有没有办法以编程方式检查函数是否存在?

5 个答案:

答案 0 :(得分:6)

代码:

window[functions [i]]

正在检查window['ff.showAlert'],但您真正想要检查的是:

window['ff']['showAlert']

window.ff.showAlert

为此,您需要遍历命名空间(window - > ff - > ...):

function methodIsDefined(fn, obj) {
  var ns = fn.split('.');
  fn = ns.pop();
  do {
    if (!ns[0]) {
      return typeof obj[fn] === 'function';
    }
  } while(obj = obj[ns.shift()]);
  return false;
}

E.g。

methodIsDefined('ff.showAlert', window); // => true
methodIsDefined('ff.foo', window); // => false

答案 1 :(得分:2)

您的问题在于命名空间。字符串"ff.showAlert"不引用函数window['ff']['showAlert'],而是引用window['ff.showAlert'],这是一个重要的区别。您声明的函数实际上由window['ff']['showAlert']引用。所以你要检查它存在的地方是错误的。

如果要检查此类命名空间函数是否存在,首先必须拆分字符串,然后遍历DOM以查找正确的属性。代码将类似于以下内容(未经测试!):

function checkFunction( name ) {

  var path = "ff.showAlert".split( '.' ),
      runner = window;

  for( var i=0; i<path.length; i++ ) {
    if( path[i] in runner ) {
      runner = runner[ path[i] ];
    } else {
      return false;
    }
  }
  return runner;
}

修改

正如@VirtualBlackFox在评论中所指出的:上述解决方案仅在函数声明在window范围之下时才有效。如果它在另一个函数的范围内,则必须将该范围作为附加参数传递并在那里搜索。

即使在这种情况下,也无法检查是否存在某些闭包构造中定义的函数。

答案 2 :(得分:0)

您需要拆分多部分功能名称,例如'ff.showAlert'。另外,因为您将ff指定为var,所以它不会是window的成员,除非它在任何函数范围之外。你的代码示例是否存在并不是很清楚。

无论如何,下面的函数允许你传入一个基础对象,以防你需要指定window以外的一个,并且它会拆分多部分函数名称:

function isFnDefined(fnName, baseObj) {
    try {
        var parts = fnName.split('.'),
            ii;

        // If no baseObj was provided, default to 'window'.
        baseObj = baseObj || window;

        for (ii in parts) {
            baseObj = base[parts[ii]];
        }

        return typeof baseObj === 'function';
    }
    catch (e) {
        return false;
    }
}​

isFnDefined('alert');          // returns true
isFnDefined('undefinedFunc');  // returns false
isFnDefined('ff.showAlert');   // returns true, if ff is a member of window 
isFnDefined('showAlert', ff);  // returns true

答案 3 :(得分:-1)

您需要使用eval():http://www.w3schools.com/jsref/jsref_eval.asp

答案 4 :(得分:-2)

你有一个字符串代表当前范围内的东西,你想知道它是什么,解决方案是评估字符串。

var f = undefined;
try
{
    f = eval(functions[i]);
}
catch(ReferenceError) {}
console.log(typeof f);

但是你为什么要在输入对象中存储字符串而不是函数?

此外,如果您可以强制每个字符串作为相对于窗口的引用(当前范围中没有'var'或来自另一个范围的闭包的内容),那么@Sirko解决方案可能是最好的。< / p>