ES6中JS类实现的解读

简介: ES6中JS类实现的解读

在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
相关文章
|
3月前
|
JavaScript 前端开发 网络架构
ES6解构赋值详解;全面掌握:JavaScript解构赋值的终极指南
解构赋值是一个强大且灵活的工具,它使得从数组和对象中提取数据变得更加简单和直观。通过掌握解构赋值的基本语法和实践,你可以写出更加简洁、可读性更强的代码。在实际项目中,解构赋值广泛应用于函数参数处理、变量交换、嵌套结构操作等场景,极大地提升了代码的灵活性和简洁度。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
7月前
|
存储 JavaScript 前端开发
JS的ES6知识点
【10月更文挑战第19天】这只是 ES6 的一些主要知识点,ES6 还带来了许多其他的特性和改进,这些特性使得 JavaScript 更加现代化和强大,为开发者提供了更多的便利和灵活性。
173 58
|
7月前
|
JavaScript 前端开发 安全
ECMAScript 6(以下简称 ES6)的出现为 JavaScript 带来了许多新的特性和改进,其中 let 和 const 是两个非常重要的关键字。
ES6 引入了 `let` 和 `const` 关键字,为 JavaScript 的变量管理带来了革新。`let` 提供了块级作用域和暂存死区特性,避免变量污染,增强代码可读性和安全性;`const` 用于声明不可重新赋值的常量,但允许对象和数组的内部修改。两者在循环、函数内部及复杂项目中广泛应用,有助于实现不可变数据结构,提升代码质量。
99 5
|
8月前
|
JavaScript 前端开发 索引
JavaScript ES6及后续版本:新增的常用特性与亮点解析
JavaScript ES6及后续版本:新增的常用特性与亮点解析
280 4
|
8月前
|
自然语言处理 JavaScript 前端开发
JavaScript高级——ES6基础入门
JavaScript高级——ES6基础入门
102 1
|
8月前
|
前端开发 JavaScript 小程序
JavaScript的ES6中Promise的使用以及个人理解
JavaScript的ES6中Promise的使用以及个人理解
84 1
|
9月前
|
JavaScript 前端开发 Oracle
软件工程师,学习下JavaScript ES6新特性吧
软件工程师,学习下JavaScript ES6新特性吧
75 9
|
7月前
|
前端开发 JavaScript
JavaScript新纪元:ES6+特性深度解析与实战应用
【10月更文挑战第29天】本文深入解析ES6+的核心特性,包括箭头函数、模板字符串、解构赋值、Promise、模块化和类等,结合实战应用,展示如何利用这些新特性编写更加高效和优雅的代码。
176 0
|
9月前
|
JavaScript 前端开发 开发者
JavaScript 类继承
JavaScript 类继承
52 1
|
9月前
|
JavaScript 前端开发 Java
JavaScript 类知识点概览
概览JavaScript中类的知识点,包括类的定义和实现、添加方法和get/set方法、类的继承和静态方法的使用。通过学生类和人员类的例子,演示了类的构造器、方法定义、继承关系和静态方法的调用。
JavaScript 类知识点概览