ES6中JS类实现的解读

news/2024/9/24 10:09:17/

在ES5及以前版本,是没有真正意义上类的概念,只是通过构造函数来模拟类的运用。尽管JS脚本语言是一门解释型弱语言,对类的需求意义不大,但ES6还是引入类的实现,让JS真正够上面向对象编程门槛,尽管对类的功能实现还不全面、彻底,但基本面向对象编程功能具有了。

一、ES5中的近类结构

由构造函数实现的近类能够对功能代码进行抽象定义与封装,实现代码重复运用与安全性,具有部分类的作用。但还不能算真正意义的类,因为它只有实例化运用功能,不具有类的直接继承与派生(只能通过间接方法),不能够对方法进行重写与多态、重载等表现。

function PersonType(name){//定义构造函数

       this.name=name;

}

PersonType.prototype.sayName=function(){//通过原型方法,给构造“类”添加方法

       console.log(this.name);

}

var person=new PersonType("张小玉");//实例化一个构造“类”

person.sayName(); //输出结果:张小玉

console.log(person instanceof PersonType);//输出结果:true

console.log(person instanceof Object);//输出结果:true

二、ES6中实现真正的类结构

(一)类的声明

class PersonClass{//或者写成:let PersonClass=class{

       //等价于构造函数

       constructor(name){

              this.name=name;

       }

       //等价于PersonType.prototype.sayName

       sayName(){

              console.log(this.name);

       }

}

let person=new PersonClass("张小玉");

person.sayName();//输出结果:张小玉

console.log(person instanceof PersonClass);//输出结果:true

console.log(person instanceof Object);//输出结果:true

console.log(typeof PersonClass);//输出结果:function

console.log(typeof PersonClass.prototype.sayName);//输出结果:function

从上可以看出,JS类的结构从本质上看还是函数,说明ES6的JS类还是对以前构造函数的包装,只是被打上了真正类的一些行为标签。

(二)为何要在ES6中引入类语法

1.以前的函数(包括构造函数)是要在作用域中被提升,而ES6的类不会被提升,它会处于临时死区中,也let定义一样,可以克服各种冲突与安全性问题。

2.类声明中所有代码将自动运行在严格模式下,而且无法强化让代码脱离严格模式。

3.构造函数的方法不可枚举,而类方法可以枚举。

4.在类中,如果调用没有通过[[construct]]定义过的方法会报错,而构造函数会默认采用新增方法,不会产生调用错误,这可能会造成较多误解。

三、ES6中类的功能实现

(一)静态成员实现

1.构造函数的静态成员实现

function PersonType(name){//定义构造函数

       this.name=name;

}

//静态方法

PersonType.crate=function(name){

       return name;

}

//实例方法

PersonType.prototype.sayName=function(){

       console.log(this.name);

}

var person=PersonType.crate("张小玉");//静态方法必须直接访问,不能在实例对象中访问

console.log(person);//输出结果:张小玉

2.ES6中类的静态成员实现

class PersonClass{

//等价于构造函数

       constructor(name){

              this.name=name;

       }

//等价于PersonType.prototype.sayName

       sayName(){

              console.log(this.name);

}

       //等价于PersonType.create

       static creat(name){

              return name;

       }

}

let person=PersonClass.creat("张小玉");//静态方法必须直接访问,不能在实例对象中访问

console.log(person); //输出结果:张小玉

(二)继承与派生

1.定义

class Rectangle{//定义父类

constructor(length,width){

       this.length=length;

       this.width=width;

}

getArea(){

        return this.length*this.width;

}

}

class Square extends Rectangle{//定义子类

       constructor(length){//继承派生方法

              super(length,length);//通过super方法访问父类构造方法

       }

}

var square=new Square(3);

console.log(square.getArea());//输出结果:9

console.log(square instanceof Square);//输出结果:true

2.使用super()方法的注意事项

(1)只可在派生类的构造函数中使用super(),如果尝试在非extends声明的类使用会抛出错误,反之如果在继承派生类中不使用super()方法继承父类,则系统会自动派生super(…args),将父类构造方法继承过来。

(2)在构造函数中访问this之前一定要调用super(),它负责初始化this,否则将出错。

(3)如果不想调super(),唯一的方法是让类的构造函数返回一个对象。

(三)类方法的遮蔽与重写

继承子类会自动遮蔽父类方法,需要进行方法的重写,因此在实例中就不会直接调用父类方法,如果需要调用,则需要在重写方法中用super()进行调用。

class Rectangle{//定义父类

       constructor(length,width){

              this.length=length;

              this.width=width;

       }

       getArea(){

              return "父类中抽象方法,未实现";

       }

}

class Square extends Rectangle{//定义子类

       constructor(length){//派生方法

              super(length,length);//通过super方法访问父类构造方法

       }

       //覆盖并遮蔽Rectangle的geArea()方法

       getArea(){

              return this.length*this.width;//在使用this之前,必须调用super

       }

}

var square=new Square(3);

console.log(square.getArea());//输出结果:是9,而不是父类中的getArea()方法的输出"父类中抽象方法,未实现"

如果要想在子类中使用父类的方法,则需要在重写方法中调用super()方法,如下

class Rectangle{//定义父类

       constructor(length,width){

              this.length=length;

              this.width=width;

       }

       getArea(){

              return "父类中抽象方法,未实现";

       }

}

class Square extends Rectangle{//定义子类

       constructor(length){//派生方法

              super(length,length);//通过super方法访问父类构造方法

       }

       //覆盖并遮蔽Rectangle的geArea()方法

       getArea(){

              return super.getArea();

       }

}

var square=new Square(3);

console.log(square.getArea());//输出结果:父类中抽象方法,未实现

(四)静态成员继承

    class Rectangle{//定义父类

              constructor(length,width){

                     this.length=length;

                     this.width=width;

              }

              getArea(){

                     return this.length*this.width;

              }

              static create(length,width){

                     return new Rectangle(length,width);

              }

       }

       class Square extends Rectangle{//定义子类

              constructor(length){//派生方法

                     super(length,length);//通过super方法访问父类构造方法

              }

              //覆盖并遮蔽Rectangle的geArea()方法

              getArea(){

                     return super.getArea();

              }

       }

       var rect=Square.create(3,4);//因为是静态方法,直接调用,不能实例化中调用

       console.log(rect.getArea());//输出结果:12


http://www.ppmy.cn/news/1529767.html

相关文章

Elastic 的 OpenTelemetry PHP 发行版简介

作者:Pawel Filipczak 宣布 OpenTelemetry PHP 的 Elastic 发行版的第一个 alpha 版本。在本篇博文中了解使用 OpenTelemetry 来检测 PHP 应用程序是多么简单。 我们很高兴推出 OpenTelemetry PHP 的 Elastic Distribution 的第一个 alpha 版本。在这篇文章中&…

ELK-01-elasticsearch-8.15.1安装

文章目录 前言一、下载elasticsearch二、将tar包放到服务器三、解压tar包四、更改配置文件五、添加启动用户六、用elasticserch用户启动6.1 报错6.2 解决问题16.3 解决问题26.4 再次用elasticserch用户启动6.5 windows浏览器打开 七、设置开机自动启动7.1 创建启动脚本7.2 在脚…

C++ set 和 map学习

一、set(multiset)的基本知识和使用 set也是一种我们直接可以使用的容器&#xff0c;使用应该包含 #include <set> 这个头文件。此处暂且不讨论其底层&#xff0c;只探讨set如何使用即可。 我们看到&#xff0c;set 的模板参数有三个&#xff0c;第一个就是其存储的数据…

秋招面试准备:《小米2024数字芯片岗面试题》

在数字芯片设计的浪潮中&#xff0c;验证工程师的角色愈发重要。他们如同守门人&#xff0c;确保每一块芯片在投入市场前都能稳定、高效地运行。小米&#xff0c;作为全球知名的智能设备制造商&#xff0c;对数字芯片岗位的人才选拔尤为严格。 本文分享《小米2024数字芯片岗面…

GitLab 批量创建用户

GitLab 批量创建用户 引言 在团队管理中&#xff0c;经常需要为多个新成员创建 GitLab 账户。手动创建每个账户不仅耗时&#xff0c;而且容易出错。为了提高效率&#xff0c;我们可以编写一个简单的 Bash 脚本来批量创建用户。本文将详细介绍如何使用 GitLab API 和 Bash 脚本…

【教程】最新可用!Docker国内镜像源列表

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 镜像加速器地址 用法示例 一、自动配置地址 二、配置单次地址 镜像加速器地址 Docker镜像加速站https://hub.uuuadc.top/docker.1panel.live…

前端项目package.json文件对象属性介绍

1. name - 项目名称&#xff0c;通常用于在 npm 注册表中标识项目。 2. version - 项目版本&#xff0c;遵循 语义化版本控制&#xff08;Semantic Versioning&#xff09;规则 3. description - 项目的简短描述。 4. main - 项目的主入口文件&#xff0c;通常是项目的主 JavaS…

shardingjdbc介绍

文章目录 1、shardingjdbc介绍1.1、读写分离、数据分片&#xff08;分库分表&#xff09;中间件&#xff1a;1.1.1、shardingsphere1.1.2、mycat 2、shardingjdbc-demo搭建2.1、创建项目2.2、添加依赖2.3、application.yml2.4、创建实体类 User2.5、创建 UserMapper2.6、创建测…