【问题标题】:Javascript "Not a Constructor" Exception while creating objects创建对象时出现Javascript“不是构造函数”异常
【发布时间】:2012-04-23 19:58:38
【问题描述】:

我正在定义一个这样的对象:

function Project(Attributes, ProjectWidth, ProjectHeight) {
    this.ProjectHeight = ProjectHeight;
    this.ProjectWidth = ProjectWidth;
    this.ProjectScale = this.GetProjectScale();
    this.Attributes = Attributes;

    this.currentLayout = '';

    this.CreateLayoutArray = function()
    {....}
}

然后我尝试创建一个这样的实例:

var newProj = new Project(a,b,c);

但是抛出了这个异常:

Project is not a constructor

可能出了什么问题?我用谷歌搜索了很多,但我仍然无法弄清楚我做错了什么。

【问题讨论】:

  • 出于好奇,哪个浏览器给出“项目不是构造函数”消息?
  • 作为一个不相关的侧节点,一般 JavaScript 风格指南建议仅当它是构造函数时才以大写字母开头变量标识符:“Project”可以,但“ProjectHeight”中的前导大写建议我认为它也应该是一个构造函数。如果您改用“projectHeight”,您的代码将对其他人更具可读性。 (事实上​​,如果其他发帖者是正确的,并且您已经在其他地方定义了一个 Project 变量,那么使用仅用于构造函数的前导大写规则将避免您再次犯该错误。)
  • @DaggNabbit Opera 确实 (12.15)

标签: javascript object constructor typeerror


【解决方案1】:

在浏览中(假设您的应用正在运行),检查、获取并确保加载了构造函数的 javascript 文件。

【讨论】:

    【解决方案2】:

    对我来说,这是 ES6 上 importrequire 之间的区别。

    例如

    processor.js

        class Processor {
        
        }
        
        export default Processor
    

    index.js

    const Processor = require('./processor');
    const processor = new Processor() //fails with the error
        
    import Processor from './processor'
    const processor = new Processor() // succeed
    

    【讨论】:

    • 有效!有没有办法让它与require() 函数一起工作?
    • 要使要求工作,您必须require('./processor').Processor,对吗?还是我错过了不适用于课程的特殊条款?
    • @baranskistad 这就是我遇到的错误,我看到const ClassName = require("library").ClassName; 在其他代码中工作,您可以很好地实例化该类,但现在我尝试了它,它不适用于不同的代码。想知道它是否是我正在使用的 SDK 本身。
    • @Raptor export Processor with module.exports 和 import with destructuring 将使 require() 工作。请参阅我对这个问题的回答。
    • 还要确保您已从正确的文件中导入/需要。如果您使用来自错误文件的命名导入,则变量将为undefined,并且您会收到无用的错误消息。通过console.log 来检查您的预期构造函数是否具有值很容易。
    【解决方案3】:

    我在尝试将 BS5ModalJS 与 webpack 结合使用时遇到了类似的错误,这意味着我正在尝试导入 js 文件。

    因为提供的单个 .js 文件设计为通过脚本标签使用,所以我花了一段时间才意识到为了避免“BSModal 不是构造函数”错误,我不得不进入他们的代码并添加:

    export {BSModal}
    

    然后我就可以使用了

    import { BSModal } from './../thirdparty/BS5ModalJS/BS5Modal.js';
    

    然后做

    让 myModal enter code here= new BSModal(...)

    没有得到那个错误。

    因此,如果您使用的是 webpack,也许要确保将类和函数导出(因此可用)给调用者。

    【讨论】:

      【解决方案4】:

      为了添加我在遇到此问题时发现的解决方案,我包含了另一个文件中的一个类,而我尝试在其中实例化它的文件给出了“不是构造函数”错误。最终问题是在定义类之前另一个文件中有几个未使用的要求。我不知道他们为什么把它弄坏了,但是把它们去掉就修复了。始终确保检查您正在考虑的步骤之间是否隐藏了某些东西。

      【讨论】:

        【解决方案5】:

        有时这就是您导出和导入它的方式。对于此错误消息,可能是缺少 default 关键字。

        export default SampleClass {}
        

        在哪里实例化它:

        import SampleClass from 'path/to/class';
        let sampleClass = new SampleClass();
        

        选项 2,带花括号:

        export SampleClass {}
        import { SampleClass } from 'path/to/class';
        let sampleClass = new SampleClass();
        

        【讨论】:

        • OP 没有显示他正在使用任何 ES6 语法。 es6 导入特性真的会影响他的代码吗?
        • 我得到了与问题标题相同的错误。也许它可以帮助其他人。
        【解决方案6】:

        我正在将一个文件中的一个类导入到测试文件中:

        //Vec.js
        class Vec {
        
        }
        
        module.exports.Vec = Vec;
        

        变化

        //Vec.test.js
        const Vec = require('./Vec');
        const myVec = new Vec(); //TypeError: Vec is not a constructor
        

        //Vec.test.js
        const {Vec} = require('./Vec');
        const myVec = new Vec(); //Succeeds!
        

        为我解决了这个错误。

        【讨论】:

        • 您正在混合使用 es5/es6 语法。你真的应该坚持一个。此外,您正在混淆导入功能。在您的第一个示例中,您正在导入整个模块并尝试从中创建一个对象。在您的第二个示例中,您仅从模块中导入“Vec”类,该类能够实例化一个对象。
        【解决方案7】:

        问题中发布的代码无法生成该错误,因为Project 不是用户定义的函数/有效的构造函数。

        function x(a,b,c){}
        new x(1,2,3);               // produces no errors
        

        你可能做过这样的事情:

        function Project(a,b,c) {}
        Project = {};               // or possibly   Project = new Project
        new Project(1,2,3);         // -> TypeError: Project is not a constructor
        

        使用var 的变量声明是hoisted,因此总是在其余代码之前进行评估。因此,这也可能导致问题:

        function Project(){}
        function localTest() {
            new Project(1,2,3); // `Project` points to the local variable,
                                // not the global constructor!
        
           //...some noise, causing you to forget that the `Project` constructor was used
            var Project = 1;    // Evaluated first
        }
        

        【讨论】:

        • 至少在 chrome 中,似乎有几种非功能/非 ctor 相关消息的变体。您的示例给出了“TypeError:对象不是函数”。 new NodeList 给出“TypeError:非法构造函数”。 new Function.prototype 给出了与 OP 消息最接近的内容:“TypeError: function Empty() {} is not a constructor。”很有趣,嗯?
        • @RobW:我认为在您的第二个示例中,本地“项目”的意思是不是作为构造函数,对吧?
        • @RobW:是的,但是您的示例不会导致“无构造函数”错误,它只会使用错误的错误?我以为你是关于 var 关键字,它在执行函数之前初始化本地范围的变量。
        【解决方案8】:

        造成这种情况的另一个原因可能是 ES2015 arrow functions它们不能用作构造函数

        const f = () => {};
        new f(); // This throws "f is not a constructor"
        

        【讨论】:

        • 有什么特别提到的理由吗?
        • @Amndeep7 我的猜测是因为new 将构造对象作为this 传递给构造函数,但箭头函数始终具有封闭范围的this
        • 谢谢。我忘了那个“陷阱”
        【解决方案9】:

        我只想补充一点,如果构造函数是从不同的文件中调用的,那么就像忘记导出构造函数一样简单

        module.exports = NAME_OF_CONSTRUCTOR
        

        也会导致“Not a constructor”异常。

        【讨论】:

          【解决方案10】:

          汽车.js

          class Car {
           getName() {return 'car'};
          }
          export default Car;
          

          TestFile.js

          const object = require('./Car.js');
          const instance = new object();
          

          错误:TypeError:实例不是构造函数

          打印对象的内容

          object = {default: Car}
          

          将默认值附加到 require 函数,它将作为构造函数工作

          const object = require('object-fit-images').default;
          const instance = new object();
          instance.getName();
          

          【讨论】:

            【解决方案11】:

            发生这种情况是因为您必须在代码中使用了另一个名为“project”的变量。就像是 var project = {}

            为了使代码正常工作,更改如下:

            var project = {} 转为var project1 = {}

            【讨论】:

            • 感谢您的回答,但我真的不明白这如何提供其他答案尚未解决的问题。就像 2012 年的 accepted answer
            【解决方案12】:

            我遇到了类似的错误,我的问题是变量名称和构造函数名称的名称和大小写相同,这不起作用,因为 javascript 将预期的构造函数解释为新创建的变量。

            换句话说:

            function project(name){
                this.name = name;
            }
            
            //elsewhere...
            
            //this is no good! name/case are identical so javascript barfs. 
            let project = new project('My Project');
            

            不过,只需更改大小写或变量名即可解决问题:

            //with a capital 'P'
            function Project(name){
                this.name = name;
            }
            
            //elsewhere...
            
            //works! class name/case is dissimilar to variable name
            let project = new Project('My Project');
            

            【讨论】:

              【解决方案13】:

              补充@wprl 的答案,ES6 对象方法简写,如箭头函数,也不能用作构造函数。 ?

              const o = {
                a: () => {},
                b() {},
                c: function () {}
              };
              
              const { a, b, c } = o;
              
              new a(); // throws "a is not a constructor"
              new b(); // throws "b is not a constructor"
              new c(); // works
              

              【讨论】:

                【解决方案14】:

                在我的例子中,我忘记了在导出模块中包装我所有代码的函数定义末尾的打开和关闭括号。 IE。我有:

                (function () {
                  'use strict';
                
                  module.exports.MyClass = class{
                  ...
                );
                

                代替:

                (function () {
                  'use strict';
                
                  module.exports.MyClass = class{
                  ...
                )();
                

                编译器不会抱怨,但是导入模块中的 require 语句没有设置它被分配给的变量,所以在你尝试构造它时它是未定义的,它会给出TypeError: MyClass is not a constructor 错误。

                【讨论】:

                  【解决方案15】:

                  对于我的项目,问题原来是由 require() 调用创建的循环引用:

                  y.js:
                  var x = require("./x.js");
                  var y = function() { console.log("result is " + x(); }
                  module.exports = y;
                  
                  x.js:
                  var y = require("./y.js");
                  var my_y = new y(); // <- TypeError: y is not a constructor
                  var x = function() { console.log("result is " + my_y; }
                  module.exports = x;
                  

                  原因是当它试图初始化 y 时,它在依赖系统中创建了一个临时的“y”对象(不是类,对象!),它在某种程度上还不是构造函数。然后,当 x.js 完成定义后,它可以继续使 y 成为构造函数。只是,x.js 在尝试使用非构造函数 y 时出现错误。

                  【讨论】:

                  • 感谢您发布此内容 - 刚刚遇到了完全相同的场景。
                  • 感谢您发布此信息!看来我遇到了同样的问题。您是如何解决这个问题的?
                  • 如果你和我一样认为 Firefox 有一个奇怪的 JIT 错误,那么这个答案可以提供一个重要的见解:CommonJS 无法处理循环引用彼此的模块!如果我的包管理器(Webpack)会在循环引用案例的日志中提供某种错误,那就太好了,但它没有......相反,它通过从 require 语句返回一个普通函数来破坏循环引用.令人困惑!当我在 Firefox 中使用带有循环引用构造函数的 instanceof 运算符时,我非常明确地看到了这个“不是构造函数”错误。哎呀!
                  • 使用 var 而不是 const 修复了错误var Target = require('./target.js');
                  • 这是我的问题。
                  【解决方案16】:

                  在我的例子中,我使用原型名称作为对象名称。例如

                  function proto1()
                  {}
                  
                  var proto1 = new proto1();
                  

                  这是一个愚蠢的错误,但可能对像我这样的人有所帮助;)

                  【讨论】:

                  • 经过数小时的调试,这就是我的解决方案。谢谢!
                  【解决方案17】:

                  我也搜索了一下,找到了这个解决方案:

                  你有一个变量Project 不是一个函数。然后new 运营商会抱怨它。在您将其用作构造器的地方尝试console.log(Project),您会找到它。

                  【讨论】:

                    猜你喜欢
                    • 2017-12-04
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-03-20
                    • 2011-10-24
                    • 2018-06-12
                    • 1970-01-01
                    • 2023-03-15
                    相关资源
                    最近更新 更多