3

関数が定義されているかどうかを確認したい(方法は関係ありません。つまり、呼び出し可能です)

サンプルコード:

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

ライブデモ
関数が存在するかどうかをプログラムでチェックする方法はありますか?

4

5 に答える 5

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

例えば

methodIsDefined('ff.showAlert', window); // => true
methodIsDefined('ff.foo', window); // => false
于 2012-05-04T13:08:27.720 に答える
2

あなたの問題は名前空間にあります。文字列"ff.showAlert"は functionwindow['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-scope の下で宣言されている場合にのみ機能します。別の関数のスコープ内にある場合は、そのスコープを追加のパラメーターとして渡し、そこで検索する必要があります。

その場合でも、たとえばいくつかのクロージャ構成内で定義されている関数の存在をチェックすることはできません。

于 2012-05-04T13:01:14.807 に答える
0

のようなマルチパート関数名を分割する必要があります'ff.showAlert'。また、ffvar として指定したため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
于 2012-05-04T13:14:11.107 に答える
-1

eval() を使用する必要があります: http://www.w3schools.com/jsref/jsref_eval.asp

于 2012-05-04T13:02:01.910 に答える
-2

現在のスコープ内の何かを表す文字列があり、それが何であるかを知りたい場合、解決策は文字列を評価することです。

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

しかし、入力オブジェクトに関数自体ではなく文字列を格納するのはなぜですか?

また、すべての文字列をウィンドウに相対的な参照にすることができる場合 (現在のスコープに「var」がないか、別のスコープの閉鎖から来るもの)、@Sirkoソリューションが最適なソリューションになる可能性があります。

于 2012-05-04T13:03:10.860 に答える