JavaScript错误:"不是一个函数"

52

看起来"$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 可能 已经找到,因为我没有收到“无法找到......”的消息,代码继续尝试初始化它。但是Firebug告诉我API.LMSInitialize不是一个函数,如果我尝试使用alert(Object.getOwnPropertyNames(API));进行调试,它会给我一个空的 alert。

我漏掉了什么?


1
API = getAPI(); 后面紧接着执行 console.log(API),你会得到什么结果? - m90
请问在初始化之后你想要做什么? - Kanak Vaghela
1
我遇到了循环依赖的错误。也许这会帮助其他人。 - SadSeven
我遇到了循环依赖的错误。创建了一个 abc_2.js 文件来解决它。 - Manohar Reddy Poreddy
7个回答

32

如果需要更多关于调试此类问题的通用建议,MDN有一篇很好的文章TypeError: "x" is not a function

尝试将一个值作为函数调用,但该值实际上不是函数。某些代码期望您提供一个函数,但这并没有发生。

也许函数名中有拼写错误?也许您调用方法的对象没有这个函数?例如,JavaScript对象没有map函数,但JavaScript数组对象有。

基本上,对象(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();


2
我想补充一点:不要把局部变量命名为与函数相同的名称,这样当您调用 showOrderForm() 时,showOrderForm 的类型将是布尔型。 - Noumenon
你提供了一些救命稻草般的建议,关于函数的问题,因为有些东西正在等待函数,但它却得到了对象或数组,真是太好的建议了! - Raj Gohil

29

你的 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();

我能在其他的this.AfterLMSInitialize = function(){}中调用this.LMSInitialize(parm)吗? - dellos

9

我也遇到过这个错误。在我的情况下,根本原因与异步相关(在代码库重构期间):一个异步函数构建了对象,该“非函数”函数所属的对象没有被await,随后尝试调用该函数会抛出错误,以下是示例:

const car = carFactory.getCar();
car.drive() //throws TypeError: drive is not a function

修复方法如下:
const car = await carFactory.getCar();
car.drive()

分享这篇文章是为了帮助那些遇到这个错误的人。


1

除了以上流行的答案,如果你正在使用服务或辅助函数文件,并在这些函数上进行export操作以供后续在项目中import

确保你导入的函数名称与从服务、辅助或工具文件导出的函数名称完全匹配,并且该函数确实存在于正确的文件中!我曾经因为这个错误而卡住,调试了几个小时,直到我发现了这个问题。


0
在我的情况下,在大量的stackoverflow搜索之后,我发现这里需要一个函数...只是一个愚蠢的拼写错误,我忘记在下一行指令的开头放置$
 function o_chir(id,nom) {
        _id_ochirish = id
        _nom= nom  
//here it threw that "Uncaught TypeError: nom is not a function"       
        ('#nom').val(s_)
        $('#o_chir').modal('show')
    }

而且 PHPStorm 没有给出任何警告


0

在 Next.js 上遇到了同样的问题。在 _app.tsx 中,我忘记将组件与包含所有身份验证函数的 AuthProvider 包装起来。


-1

我在使用JSON.parse和JSON.stringify()时错误地复制了一个类对象导致出现了这个错误,该错误会移除函数,如下:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  // Method
  calcArea() {
    return this.height * this.width;
  }
}

const square = new Rectangle(10, 10);

console.log('area of square: ', square.calcArea());

const squareCopy = JSON.parse(JSON.stringify(square));

// Will throw an exception since calcArea() is no longer function 
console.log('area of square copy: ', squareCopy.calcArea());

@Liam 我想表达的是我以错误的方式克隆了一个类。我并不是想说这是你应该克隆类的方式。我会更新我的答案,使之更加清晰。 - dustydojo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接