(js)使用new对函数进行构造调用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(js)使用new对函数进行构造调用相关的知识,希望对你有一定的参考价值。

参考技术A

js中的函数有两种调用方式,一种是通过普通的声明之后进行的调用。一种是通过new关键字进行构造调用。普通的调用就是依次执行函数内部的函数语句,如果有返回值则返回返回值,如果没有则函数内部的声明周期结束。但是,函数还有另一个调用方式,使用new关键字,将函数当做构造函数。js中没有所谓独立出来的构造函数的概念,所有的函数都用同样的方式声明,所以有了new这个关键字,js(ES6之前)只能通过这种方式实现构造器的构造。那么使用new关键字跟普通的调用有什么区别呢?

使用new关键字,比普通的函数调用,主要分为以下四个步骤:

稍后我们会对上面的四句话逐一解析,首先我们看一看函数调用的两种方式:

这样看来,两者似乎没有区别,但是这里要注意,使用new进行构造调用时,函数是有返回值的。

上面的return2并没有返回一个函数。

其实它会返回一个空的对象。这也就是上面使用new关键词的第一步, 内部创建一个新的空对象

那么当函数内部有this时,结果会是怎样的呢?

使用new关键字后,在函数内部如果出现了this,则自动将this指向内部新建的对象上。最后返回时,因为this的缘故,对象上新建了a属性,并且赋值返回。

修正定义的对象Object的[[prototype]]
虽然实例上的[[prototype]]属性__proto__是ES6才作为规范出版的。但是在这之前chrome已经支持__proto__属性,他指向对象的原型。

原型的问题相当复杂,单独拿出来也可以当好几篇文章的量来讲。但是这并不是本文的重点。但是每一个对象从根部来说,继承自Object。而Object.prototype上面定义了一些方法,有类似toString,valueOf等等等方法。对于对象来说,支持通过属性链和方法链向上查询。所以在一个对象实例中,如果没有定义toString方法,但它还可以向上查询,找到原型中的toString方法,进行调用。

同时的,有很多元素通过Object实现继承。比如Function, Array, RegExp等等对象,它们也是对象,但是却是继承来自Object。

在这里,内部定义的对象,让他继承来自构造函数。

最后一步,也是最容易被忽略的一步,那就是当构造函数存在返回值时,并且返回值为对象时,返回对象而不返回之前定义的对象。

当然,上面说的Function,Array,RegExp也算Object的一种,如果返回他们同样也会阻止默认的对象返回。

使用 TypeScript 在 Node.js 中进行 Sequelize - 没有“new”就无法调用类构造函数模型

【中文标题】使用 TypeScript 在 Node.js 中进行 Sequelize - 没有“new”就无法调用类构造函数模型【英文标题】:Sequelize in Node.js with TypeScript - Class constructor Model cannot be invoked without 'new' 【发布时间】:2020-05-10 06:14:15 【问题描述】:

我正在尝试在 Node.js + TypeScript 中使用 Sequelize。我正在尝试使用以下简单代码:

import Sequelize, Model, DataTypes from 'sequelize';

const sequelize = new Sequelize('base', 'user', 'pass', dialect: 'mysql');

class User extends Model 

User.init(
    id: 
        type: DataTypes.INTEGER.UNSIGNED,
        autoIncrement: true,
        primaryKey: true,
        unique: true,
    ,
    login: 
        type: DataTypes.STRING(255),
        allowNull: false,
        unique: true,
    ,
    password: 
        type: DataTypes.STRING(255),
        allowNull: false,
    ,
, 
    tableName: 'users',
    sequelize,
);

sequelize.sync().then(() => 
    User.create(
        login: 'aaaa',
        password: 'bbbb',
    );
);

但是,当尝试运行已编译的代码时,我收到以下错误:

未处理的拒绝类型错误:类构造函数模型不能 调用时不带“新”

据我了解,这不是 sequelize 的问题:与 javascript 代码运行相同的代码运行没有问题,并在数据库适当的表中创建记录。我知道这是将 ES6 类转换为 ES5 的问题,但是我无法修复此错误。这是我的 tsconfig.json:


  "compilerOptions": 
    "experimentalDecorators": true,
    "outDir": "./dist",
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "module": "esnext",
    "target": "es5",
    "sourceMap": true,
    "moduleResolution": "node",
    "lib": ["es5", "dom", "esnext"],
    "jsx": "react",
    "typeRoots": ["./common/typings", "./node_modules/@types"]
  ,
  "exclude": [
    "node_modules"
  ]

根据我在 *** 类似问题和互联网上的各种站点中阅读的内容,将编译器选项中的目标更改为 ES6 应该可以解决问题,但即使在这样的更改之后问题仍然存在。我在这里做错了什么已经没有想法了,所以我们将不胜感激。

【问题讨论】:

【参考方案1】:

尝试在 tsconfig.json 中将目标更改为 "ES2017"。为我解决了问题。

【讨论】:

它在根目录下,叫做tsconfig.json。这是您放置打字稿配置设置的地方。【参考方案2】:

转到tsconfig.json 文件。然后,将 target 更改为 es6,如下例所示:


  "compilerOptions": 
    "target": "es6",
    "module": "commonjs",
    "declaration": true,
    "outDir": "./lib",
    "strict": true
  ,
  "include": ["src"],
  "exclude": ["node_modules", "**/__tests__/*"]

【讨论】:

这对我有用。最初我将其设置为 es5。【参考方案3】:

感谢https://***.com/users/4344732/tran-son-hoang,将"module": "commonjs" 添加到tsconfig.josn 后我已经解决了问题

"compilerOptions": 
    ...
    "module": "commonjs",
    ...
  ,

【讨论】:

以上是关于(js)使用new对函数进行构造调用的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript之用new操作符调用函数——一篇带你搞懂

详解 JS 中 new 调用函数原理

TypeError:没有'new'就不能调用类构造函数文档

2017.05.06FreeCodeCamp编程之JS面向对象编程学习

js 构造函数的返回值

你不知道的JS系列 ( 22 ) - this new 绑定