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

时间:2022-11-05 12:11:45

I want to check if a function is defined (I don't care how, I mean it is callable)

我想检查函数是否已定义(我不关心如何,我的意思是它是可调用的)

sample code:

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]]);
}

this returns:

alert : function
undefinedFunction : undefined
ff.showAlert : undefined

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

Live demo
Is there a way to programmatically check if a function exists?

现场演示有没有办法以编程方式检查函数是否存在?

5 个解决方案

#1


6  

The code:

window[functions [i]]

Is checking for window['ff.showAlert'] but what you really want to check for is:

正在检查窗口['ff.showAlert'],但你真正要检查的是:

window['ff']['showAlert']

or

window.ff.showAlert

For this, you need to traverse the namespace (window->ff->...):

为此,您需要遍历命名空间(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

#2


2  

Your problem lies within the namespacing. The string "ff.showAlert" does not reference to the function window['ff']['showAlert'], but to window['ff.showAlert'], which is an important difference. The function you declare is actually referenced by window['ff']['showAlert']. So the place, that you are checking for its existance, is wrong.

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

If you want to check for the existance of such namespaced functions, you first have to split the string and then walk through the DOM to find the correct property. The code would be something like the following (not tested!):

如果要检查此类命名空间函数是否存在,首先必须拆分字符串,然后遍历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;
}

edit

As pointed out by @VirtualBlackFox in the comments: The above solution only works if the function is declared below the window-scope. If it's inside another function's scope, you would have to pass that scope as an additional parameter and search there.

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

Even in that case you can't check for the existance of functions that are, e.g., defined inside some closure constructs.

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

#3


0  

You need to split multi-part function names like 'ff.showAlert'. Also, because you specified ff as a var, it won't be a member of window unless it's outside of any function scope. It's not really clear whether it is or not from your code example.

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

Anyway, the function below allows you to pass in a base object, in case you need to specify one other than window, and it splits multi-part function names:

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

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

#4


-1  

you need to use eval(): http://www.w3schools.com/jsref/jsref_eval.asp

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

#5


-2  

You have a string that represent something in the current scope and you want to know what it is, the solution is to eval the string.

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

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

But why are you storing strings instead of function themselves in your input object ?

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

Also if you could force every string to be a reference relative to window (No 'var' in the current scope or something coming from the closure of another scope) then @Sirko solution might be the best one.

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

#1


6  

The code:

window[functions [i]]

Is checking for window['ff.showAlert'] but what you really want to check for is:

正在检查窗口['ff.showAlert'],但你真正要检查的是:

window['ff']['showAlert']

or

window.ff.showAlert

For this, you need to traverse the namespace (window->ff->...):

为此,您需要遍历命名空间(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

#2


2  

Your problem lies within the namespacing. The string "ff.showAlert" does not reference to the function window['ff']['showAlert'], but to window['ff.showAlert'], which is an important difference. The function you declare is actually referenced by window['ff']['showAlert']. So the place, that you are checking for its existance, is wrong.

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

If you want to check for the existance of such namespaced functions, you first have to split the string and then walk through the DOM to find the correct property. The code would be something like the following (not tested!):

如果要检查此类命名空间函数是否存在,首先必须拆分字符串,然后遍历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;
}

edit

As pointed out by @VirtualBlackFox in the comments: The above solution only works if the function is declared below the window-scope. If it's inside another function's scope, you would have to pass that scope as an additional parameter and search there.

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

Even in that case you can't check for the existance of functions that are, e.g., defined inside some closure constructs.

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

#3


0  

You need to split multi-part function names like 'ff.showAlert'. Also, because you specified ff as a var, it won't be a member of window unless it's outside of any function scope. It's not really clear whether it is or not from your code example.

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

Anyway, the function below allows you to pass in a base object, in case you need to specify one other than window, and it splits multi-part function names:

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

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

#4


-1  

you need to use eval(): http://www.w3schools.com/jsref/jsref_eval.asp

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

#5


-2  

You have a string that represent something in the current scope and you want to know what it is, the solution is to eval the string.

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

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

But why are you storing strings instead of function themselves in your input object ?

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

Also if you could force every string to be a reference relative to window (No 'var' in the current scope or something coming from the closure of another scope) then @Sirko solution might be the best one.

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