当前位置: 首页 > news >正文

class与构造函数

目录

  • 回望构造函数
  • 来看class写法
    • 细微区别
  • 将class一比一转换为function写法

回望构造函数

首先回顾es6之前的构造函数写法

// 写一个构造函数
function Student(name, age) {
    this.name = name;
    this.age = age;
}
// 挂载原型方法
Student.prototype.call = function () {
    console.log("my name is " + this.name);
};
// 挂载静态方法
Student.line = function () {
    console.log("--------------------------------");
};

const xinxin = new Student('xinxin', 20);
console.log(xinxin.name, xinxin.age);
xinxin.call();
Student.line();

输出如下:
xinxin 20
my name is xinxin
------------------------------------

这种写法是具有二义性的,是通过调用方法来决定它是构造函数还是普通函数的
当我们以普通函数调用也不会报错

console.log(Student('xinxin', 20));  // undefined

反之也是,会得到一个空对象,如下:

function hello(name) {
    console.log('hello' + name);
}
const h = new hello('xinxin');
console.log(h);     // helloxinxin
                    // hello {}

来看class写法

和上面使用相同的例子

// 写一个构造函数
class Student {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
     // 挂载原型方法
    call() {
        console.log("my name is " + this.name);
    };
    // 挂载静态方法
    static line() {
        console.log("--------------------------------");
    };
}
const xinxin = new Student('xinxin', 20);
console.log(xinxin.name, xinxin.age);
xinxin.call();
Student.line();

输出如下:
xinxin 20
my name is xinxin
------------------------------------

细微区别

  1. class是没有所谓二义性的,所以自然不能用普通函数调用的方法来调用
console.log(Student('xinxin', 20));

报错:Class constructor Student cannot be invoked without ‘new’
类构造器必须要使用new

  1. 再就是class里为严格模式,不能有相同名字的参数
class Student {
    constructor(name, name) {
        this.name = name;
    }
    // 挂载静态方法
    static line () {
        console.log("--------------------------------");
    };
}
const xinxin = new Student('xinxin', 20);
console.log(xinxin.name, xinxin.age);

报错:Duplicate parameter name not allowed in this context
在这个上下文中相同的参数名是不被允许的

来看function声明的则没有这个问题

function Student(name, name) {
    this.name = name;
}
const xinxin = new Student('xinxin', 20);
console.log(xinxin.name, xinxin.age);  // 20 undefined
  1. 接下来让我们遍历两种方式创建的实例
    function
// 写一个构造函数
function Student(name, age) {
    this.name = name;
    this.age = age;
}
// 挂载原型方法
Student.prototype.call = function () {
    console.log("my name is " + this.name);
};
// 挂载静态方法
Student.line = function () {
    console.log("--------------------------------");
};

const xinxin = new Student('xinxin', 20);
for (i in xinxin) {
    console.log(i);
}
//	name age call

class

// 写一个构造函数;
class Student {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    // 挂载原型方法
    call() {
        console.log("my name is " + this.name);
    };
    // 挂载静态方法
    static line() {
        console.log("--------------------------------");
    };
}

const xinxin = new Student('xinxin', 20);
for (i in xinxin) {
    console.log(i);
}
// name age

class的原型方法不会被遍历出来,说明ES6 中的原型方法是不可被枚举的, ES6 对此也是做了特殊处理的

  1. class的方法是不能被new出来的,function声明的方法也还是function依然具有二义性也是可new可直接调用
    class
    会报错
class Student {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    // 挂载原型方法
    call() {
        console.log("my name is " + this.name);
    };
    // 挂载静态方法
    static line() {
        console.log("--------------------------------");
    };
}

const xinxin = new Student('xinxin', 20);
const acall = new xinxin.call();
console.log(acall);	// xinxin.call is not a constructor

function
依然会获得一个空对象

// 写一个构造函数
function Student(name, age) {
    this.name = name;
    this.age = age;
}
// 挂载原型方法
Student.prototype.call = function () {
    console.log("my name is " + this.name);
};
// 挂载静态方法
Student.line = function () {
    console.log("--------------------------------");
};

const xinxin = new Student('xinxin', 20);
const acall = new xinxin.call();
console.log(acall);	
// my name is undefined
// {}

将class一比一转换为function写法

看到以上它们之间是有许多区别的,class多做了许多处理,所以肯定不是简单的用function写一个就和class写的效果一样,我们还需要进行其他的操作
class原型代码还是以上面写的为例

class Student {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    // 挂载原型方法
    call() {
        console.log("my name is " + this.name);
    };
    // 挂载静态方法
    static line() {
        console.log("--------------------------------");
    };
}

分析

  1. class是在严格模式下的,所以我们也要开启严格模式
  2. 要进行类型检查,检查是否为自己的实例对象
  3. class原型方法是不能被遍历的,所以要对原型属性的属性进行修改
  4. 最后就是将它们组合到一起
// 开启严格模式
'use strict';
// 类型检查(实例,构造函数)
function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
    }
};
// 对属性值进行修改(目标对象,属性修改数组)
function _defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        // 默认不可枚举
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor)
            descriptor.writable = true;
        // 修改属性配置
        Object.defineProperty(target, descriptor.key, descriptor);
    }
}
// 最后进行组合(构造函数,原型方法,静态方法)
function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps)
        _defineProperties(Constructor.prototype, protoProps);
    if (staticProps)
        _defineProperties(Constructor, staticProps);
    return Constructor;
}

// 创建Student类
var Student = /*#__PURE__*/function (name, age) {
    // 构造器
    function Student(name, price) {
        // 进行验证
        _classCallCheck(this, Student);
        // 添加实例属性
        this.name = name;
        this.price = price;
    }
    // 添加实例方法和静态方法
    _createClass(Student, [{
        key: 'call',
        value: function () {
            console.log("my name is ".concat(this.name));
        }
    }], [{
        key: 'line',
        value: function () {
            console.log('-------------------------------');
        }
    }]);
    return Student;
}();

const xinxin = new Student('xinxin', 20);
xinxin.call();  // my name is xinxin
Student.line(); // -------------------------------

在JavaScript中,/#PURE/注释是一个特殊的注释,它告诉代码压缩工具如terser,标记的函数调用是“纯净的”,这意味着如果函数调用结果未被使用,它可以安全地删除
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

以上代码借鉴了Babel 的代码转义

相关文章:

  • Podman配置
  • AI在未来会不会代替人工???
  • Redis中AOF的实现方式和AOF重写
  • 运动规划实战案例 | 基于可视图的路径规划算法(附ROS C++/Python仿真)
  • 动态列表的数据渲染、新增、编辑等功能开发及数据处理
  • MySQL安装与基础配置(Windows版以及linux版)
  • RISCV GCC 4 后端优化
  • 国产数据库 YanshanDB 和 达梦数据库 的选型
  • PHP MySQL 创建数据库
  • 4S店汽车维修保养管理系统 (源码+lw+部署文档+讲解),源码可白嫖!
  • Spring MVC 操作会话属性详解(@SessionAttributes 与 @SessionAttribute)
  • 第二十五章:Python-pyecharts 库实现 3D 地图绘制
  • css单位
  • 通信协议详解(十):PSI5 —— 汽车安全传感器的“抗干扰狙击手”
  • el-input 中 select 方法使用报错:属性“select”在类型“HTMLElement”上不存在
  • Redis 下载 — Ubuntu22.04稳定版,配置
  • SvelteKit 最新中文文档教程(18)—— 浅层路由和 Packaging
  • 图形化编程语言:低代码赛道的技术革命与范式突破
  • TypeScript 泛型详解及应用场景
  • uniapp加载json动画
  • 网站服务器内部错误是怎么回事/短视频营销推广方式
  • js实现网站简体转繁体/哪个网站做推广效果好
  • 拱墅网站建设/谷歌play商店
  • 默认网站停止/seo优化服务是什么
  • 厦门做公司网站/国际财经新闻
  • 有哪些网站做二手房好的/营销培训视频课程免费