JavaScript编码之路【ES6新特性之Class类】(一)

简介: JavaScript编码之路【ES6新特性之Class类】(一)

前言

嘟三~ 嘟三~ 今日份广播题目:“怎么让JavaScript越来越6”。接下来,小菜鸡本人将和大家一起来探讨ES6-ES13的那些酷酷的新特性,从这次广播开始,你也可以炫耀:“这个ES新特性我都用得溜溜的!”

引子

ES6就像一盘全新研发出炉的九转大肠,它不仅保留了原来的味道,还加入了山量的新鲜元素,味道更加可口,并且设计得更加优美。同样,ES6增加了很多有用的新特性,比如类(Class)。类是什么呢?为什么要有它呢?类是一种可以实例化为对象或者继承为子类的模板,简洁明快,极大提高了代码的维护性。


一. ES6定义类

1.1. 认识class定义类

按照构造函数形式创建类,不仅仅和编写普通的函数过于相似,而且代码并不容易理解。因此在ES6(ECMAScript2015)新的标准中使用了class关键字来直接定义类,但是,其实这只不过是一个糖衣炮弹【原名:语法糖】,其核心元素是构造函数和原型链。所以学好了构造函数、原型链更有利于去理解类的概念和i其继承关系。就像你要了解为什么芥末能让你眼泪直流,你就得先知道它从哪儿来,和它是怎么做出来的。


那么,如何使用class来定义一个类呢?


想象一下,在ES6之前创建一个类,感觉就像驾驶一辆没有自动挡和助力转向的老爷车。有了ES6,你可以使用class关键字来定义一个类,这就像获得了自动挡和助力转向,让全过程简便易行。


可以使用两种方式来助力咱们

类声明

class Person {

}

类表达式

var Student = class {
  
}

接着我们就可以使用new操作符调用类

var p1 = new Person
var p2 = new Person
console.log(p1, p2)

研究一下类的一些特性吧

【探究历程】

小菜鸡创建了一个Person类的实例p, 其实也就是实例化了一个’Person

var p = new Person

首先,小菜鸡打开了持有’Person’手提箱,看见标签上写着"[class Person]"。这标签其实就像是一纸身份证明,告诉俺们’Person’是一个类。

console.log(Person) // [class Person]

接着小菜鸡翻开’Person’的后背,发现了一把钥匙,这就是我们的prototype。此时,钥匙看起来非常空洞,只有它的形状,并没有任何其他的钥匙牙,比如方法或者属性。这就是因为我们的’Person’类还没定义任何方法或属性,所以它的prototype现在看起来是个洁白的 {}。


console.log(Person.prototype) // {}

接下来,侦探从钥匙上发现了一个指纹,也就是constructor,这个指纹将我们的钥匙链接回了Person类,证明了这个原型是属于Person类的。

console.log(Person.prototype.constructor) // [class Person]

然后,看最后的打印结果,这就好比小菜鸡召唤了克隆科技,制造出了Person的克隆人。克隆人p虽然拥有自己的生命,但是他的基因,或者说__proto__还是指向他的克隆源Personprototype,表示p是从这里继承属性和方法的。

console.log(p.__proto__ === Person.prototype) // true

最后,小菜鸡拿出神秘的魔镜对Person进行了鉴定。魔镜告诉他,Person其实是一个 ‘function’ 的 disguise,因为在JavaScript中,类实质上还是函数

console.log(typeof Person) // function

【本次探究告一段落】

1.2. 类的构造函数

如果你曾经在游戏角色选择界面里,享受过为你的角色设定名字、性别、属性值的乐趣,那么你那时候其实就对于类的构造函数有一些直观的理解了。构造函数constructor就好比是你创建游戏角色的大脑,可以让定制角色的一些基本属性。

【注意】

  • 每个类都可以有一个自己的构造函数(方法),这个方法的名称是固定的constructor
  • 当我们通过new操作符,操作一个类的时候会调用这个类的构造函数constructor
  • 每个类只能有一个构造函数,如果包含多个构造函数,那么会抛出异常
class Person {
  constructor(name, age, height) {
    this.name = name
    this.age = age
    this.height = height
  }
}

var p1 = new Person("HuCE", 19, 1.50)
console.log(p1)

开始了,游戏在内存中创建了一个全新的角色(空对象)【第一步】。然后,新角色的继承链([[prototype]]属性)会链接到角色原型(即:Person.prototype)【第二步】。接下来,游戏操作界面(即:this)都指向你的新角色【第三步】。游戏开始运行(执行构造函数的内部代码)【第四步】。最终,如果你没有设定任何属性(也就是构造函数没有返回非空对象),那么角色就会当做一个全新的角色(空对象)返回【第五步】。


每个类只能有一个构造函数。会不会有人问:“哈?我不能让我的角色一次拥有两种个性吗?”答案是,当然不能。试图在一个类中设定两个构造函数,就像是你试图同时控制一个拥有两种个性的角色一样,这将引发冲突,最后会导致异常。

1.3. 类的方法定义

1.3.1. 实例方法

在上面我们定义的属性都是直接放到了this上,也就意味着它是放到了创建出来的新对象中:

对于实例的方法,我们是希望放到原型上的,这样可以被多个实例来共享,这个时候我们可以直接在类中定义

class Person {
  constructor(name, age, height) {
    this.name = name
    this.age = age
    this.height = height
  }

  running() {
    console.log(this.name + " running~")
  }

  eating() {
    console.log(this.name + " eating~")
  }
}

var p1 = new Person("why", 18, 1.88)
console.log(p1)

p1.running()
p1.eating()
// [ 'constructor', 'running', 'eating' ]
console.log(Object.getOwnPropertyNames(Person.prototype))

如果我们检查类的属性描述符,就像是查看社区规定,会发现它们的enumerable都是false,也就是说,这些方法默认是不会出现在for...in循环中的。

console.log(Object.getOwnPropertyDescriptors(Person.prototype))

1.3.2. 访问器方法

还记得对象属性描述符吗?对象可以添加setter和getter函数的,其实类也是可以的


setter?getter?What?


突然回忆起很小的时候,我躺在门前的稻谷堆里读着《哈利波特 》,忘了读到了什么,只记得太阳暖暖的,然后太阳下山了,天空红扑扑的,外婆这个时候就喊我吃饭了,真是怀念呀。

settergetter可以让我们精细地控制类的属性

  • setter其实就像是一个警卫,它坐在赋值操作的大门,检查每一个通过大门的值。就算你穿上上哈利波特的隐形衣走到setter前面,setter也不会让你直接通过。它会先确认你是不是合适的值,然后亲自把你带进来。
  • getter就像一个守门人,每当你想访问某个属性,getter就会把它安全地送到你的手上。
class Person {
  constructor(name) {
    this._name = name
  }

  set name(newName) {
    console.log("调用了name的setter方法")
    this._name = newName
  }

  get name() {
    console.log("调用了name的getter方法")
    return this._name
  }
}

var p = new Person("why")
console.log(p.name)
p.name = "kobe"
console.log(p.name)

如上,Person每次被赋值和被访问的时候,setter和getter方法都会被调用。


但在类里,这把魔法钥匙(setter和getter)其实是挂在原型的钩子上的,所有的实例都可以使用这把钥匙。这也就是说,在类中定义的setter和getter方法是放到原型上的,因此可以被所有实例共享。


var p = new Person("why")
console.log(p.name)
p.name = "kobe"
console.log(p.name)

var obj = {
  _name: "",
  set name(newName) {
    this._name = newName
  },
  get name() {
    return this._name
  }
}

console.log(obj)
console.log(Object.getOwnPropertyDescriptors(p.__proto__))

如上,创建了一个Person类和一个普通对象obj,它们都有同样的getter和setter,但obj的getter和setter是直接在对象上,而Person的getter和setter是在原型上。这就是他们的区别。


1.3.3. 静态方法

【想象时间】


有一个神奇的机器,这个机器只需要录入一个"create"命令,无需其他任何条件,就会自动生成一个Person。而我们的静态方法就是这个神奇的机器。

静态方法通常用于声明跟具体实例无关的方法,也就是说,它们常常与类的实例化对象无关。这些方法,我们一般直接用类去调用,而不是类的实例

JavaScript的类中,我们用static关键字来声明静态方法。

class Person {
  constructor(age) {
    this.age = age
  }

  static create() {
    return new Person(Math.floor(Math.random() * 100))
  }
}

for (var i = 0; i < 10; i++) {
  console.log(Person.create())
}

我们为Person类定义了一个静态方法create。这个方法会调用Person的构造函数,创建一个新的Person实例,其age属性是一个0到100的随机数。


可以看到,尽管我们没有创建任何Person的实例,但是我们仍然可以通过Person.create()方法创建Person的实例。而且不管我们调用多少次Person.create(),都不会影响到其他的Person实例,每次调用都会得到一个全新的Person实例。


这就像我们有一个人口生成器,不需要任何条件,只需要启动,就会自动生成一个人口。这种造人的能力,就是静态方法为我们提供的。



JavaScript编码之路【ES6新特性之Class类】(二):https://developer.aliyun.com/article/1556687

目录
相关文章
|
4天前
|
JavaScript 前端开发 网络架构
JavaScript编码之路【对象的增强、ES6新特性之函数的默认值设置 、rest参数 (剩余参数)、拓展运算符、对象与数组的解构赋值】
JavaScript编码之路【对象的增强、ES6新特性之函数的默认值设置 、rest参数 (剩余参数)、拓展运算符、对象与数组的解构赋值】
7 1
|
4天前
|
存储 JavaScript 前端开发
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(二)
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(二)
9 1
|
1天前
|
JavaScript
JS 自测题 —— 手写 class
JS 自测题 —— 手写 class
5 0
|
1天前
|
JavaScript 索引
js 类数组 转 数组
js 类数组 转 数组
7 0
|
4天前
|
存储 JavaScript 前端开发
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(一)
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(一)
7 0
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的个人健康管理系统小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的个人健康管理系统小程序附带文章源码部署视频讲解等
8 2
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的高校宿舍信息管理系统小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的高校宿舍信息管理系统小程序附带文章源码部署视频讲解等
7 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的电影交流平台小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的电影交流平台小程序附带文章源码部署视频讲解等
7 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的电器维修系统小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的电器维修系统小程序附带文章源码部署视频讲解等
7 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的大学生校园兼职微信小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的大学生校园兼职微信小程序附带文章源码部署视频讲解等
9 1