「$ smthは関数ではありません」はJavaScriptの非常に一般的な問題のように見えますが、かなりの数のスレッドを調べた後、私の場合に何が原因であるのかまだ理解できません。
次のように定義されたカスタムオブジェクトがあります。
_function Scorm_API_12() {
var Initialized = false;
function LMSInitialize(param) {
errorCode = "0";
if (param == "") {
if (!Initialized) {
Initialized = true;
errorCode = "0";
return "true";
} else {
errorCode = "101";
}
} else {
errorCode = "201";
}
return "false";
}
// some more functions, omitted.
}
var API = new Scorm_API_12();
_
次に、別のスクリプトで、このAPIを次の方法で使用しようとしています。
_var API = null;
function ScormProcessInitialize(){
var result;
API = getAPI();
if (API == null){
alert("ERROR - Could not establish a connection with the API.");
return;
}
// and here the dreaded error pops up
result = API.LMSInitialize("");
// more code, omitted
initialized = true;
}
_
GetAPI()のものは次のようになります。
_var findAPITries = 0;
function findAPI(win)
{
// Check to see if the window (win) contains the API
// if the window (win) does not contain the API and
// the window (win) has a parent window and the parent window
// is not the same as the window (win)
while ( (win.API == null) &&
(win.parent != null) &&
(win.parent != win) )
{
// increment the number of findAPITries
findAPITries++;
// Note: 7 is an arbitrary number, but should be more than sufficient
if (findAPITries > 7)
{
alert("Error finding API -- too deeply nested.");
return null;
}
// set the variable that represents the window being
// being searched to be the parent of the current window
// then search for the API again
win = win.parent;
}
return win.API;
}
function getAPI()
{
// start by looking for the API in the current window
var theAPI = findAPI(window);
// if the API is null (could not be found in the current window)
// and the current window has an opener window
if ( (theAPI == null) &&
(window.opener != null) &&
(typeof(window.opener) != "undefined") )
{
// try to find the API in the current window�s opener
theAPI = findAPI(window.opener);
}
// if the API has not been found
if (theAPI == null)
{
// Alert the user that the API Adapter could not be found
alert("Unable to find an API adapter");
}
return theAPI;
}
_
ここで、APIはおそらく foundです。「Unable to find ...」メッセージが表示されないため、コードはそれを初期化しようとします。しかし、firebugは_API.LMSInitialize is not a function
_を教えてくれ、alert(Object.getOwnPropertyNames(API));
でデバッグしようとすると、空のアラートを出します。
私は何が欠けていますか?
LMSInitialize
関数は_Scorm_API_12
_関数内で宣言されています。したがって、_Scorm_API_12
_関数のスコープでのみ見ることができます。
API.LMSInitialize("")
のようなこの関数を使用する場合は、次のように_Scorm_API_12
_関数を宣言します。
_function Scorm_API_12() {
var Initialized = false;
this.LMSInitialize = function(param) {
errorCode = "0";
if (param == "") {
if (!Initialized) {
Initialized = true;
errorCode = "0";
return "true";
} else {
errorCode = "101";
}
} else {
errorCode = "201";
}
return "false";
}
// some more functions, omitted.
}
var API = new Scorm_API_12();
_
この種の問題のデバッグに関する一般的なgenericアドバイスについては、MDNに良い記事があります TypeError: "x" is not a function :
関数のような値を呼び出そうとしましたが、値は実際には関数ではありません。いくつかのコードは関数を提供することを期待していますが、それは起こりませんでした。
関数名にタイプミスがあるかもしれませんか?メソッドを呼び出しているオブジェクトにこの関数がないのでしょうか?たとえば、JavaScriptオブジェクトにはマップ関数はありませんが、JavaScript Arrayオブジェクトにはあります。
基本的に、オブジェクト(js内のすべての関数もオブジェクト)は、存在すると思う場所には存在しません。これは、多数の理由を含む可能性があります(広範なリストではありません):
var x = function(){
var y = function() {
alert('fired y');
}
};
//the global scope can't access y because it is closed over in x and not exposed
//y is not a function err triggered
x.y();
var x = function(){
var y = function() {
alert('fired y');
}
};
//z is not a function error (as above) triggered
x.z();
このエラーも発生しました。私の場合、根本原因は非同期に関連していました(コードベースリファクタリング中):「関数ではない」関数が属するオブジェクトを構築する非同期関数は待機されず、その後の関数呼び出しの試みはエラーをスローします以下:
const car = carFactory.getCar();
car.drive() //throws TypeError: drive is not a function
修正は次のとおりです。
const car = await carFactory.getCar();
car.drive()
これをケースに入れて投稿すると、このエラーに直面している他の人に役立ちます。