[TOC]
>[success] # class - 类 初次见面
大家都清楚,在 **javascript 的世界** 都是用 **原型链** 与 **构造函数** 来实现 **继承** ,到了 **ES6** 时代,总算出现了 **Class** 的概念, **虽然它内部还是原型链的机制来实现**,但是我们总算有了新的方法,从我们熟悉的 **面向对象** 的方式来审视这门语言了,**Typescript** 对 **类的支持更加丰富,除了ES6、ES7有的内容,还添加了新的内容** ,首先我们来复习一下 **Class** :
1. **类(Class):定义了一切事物的抽象特点**
**定义了一切事物的抽象特点** ,包括它的 **属性** 和 **方法** , 假如说 **它就是一张汽车的图纸,上面描绘了如何制作汽车**
2. **对象(Object):类的实例**
我们可以说 **一辆宝马车是实例,一个奥迪车也是一个实例** 。
3. **面向对象(OOP)三大特性:封装、继承、多态**
1. **封装**
**封装** ,就是说对 **数据操作的细节隐藏起来,只暴露对外的接口,外界调用端不需要,也可能不知道里面的细节,只能通过对外提供的接口来访问该对象。**
****
2. **继承**
**继承** 很好理解, **子类** 可以 **继承父类** ,**子类除了拥有父类所有的特征外,还有一些更具体的特性。**
****
3. **多态**
由 **继承** 产生了相关 **不同的类** ,对 **同一个方法可以有不同的响应,比如猫跟狗,都继承自 animal(动物) 它们都继承了自己 eat(吃) 的方法,此时针对某一个实例,我们无需了解它是猫或狗,我们可以直接调用 eat 这个方法,程序会自动判断出来应该如何执行这个方法**
接下来我们根据上面讲解的意思,来写这么一个类
**class.js**
~~~
// ---------------------------------------- 1. 封装 -----------------------------
// 基本类(动物基类)
class Animal {
constructor(name){
this.name = name
}
run(){
return `${this.name} 在奔跑`
}
}
// 实例化函数
// const snake = new Animal('小狗')
// console.log(snake.run())
// ---------------------------------------- 2. 继承 -----------------------------
// 小狗继承动物这个类(派生类)
class Dog extends Animal {
bark(){
return `${this.name} 在狂吠`
}
}
// 小狗继承了动物这个类的方法
const xiaobao = new Dog('旺财')
console.log(xiaobao.run())
console.log(xiaobao.bark())
// ---------------------------------------- 3. 多态 -----------------------------
// 小猫继承动物这个类(派生类)
class Cat extends Animal {
// 静态方法
static categories = ['mammal']
constructor(name){
// 使用父类的属性,ES6中我们可以通过类,我们使用extends实现基类(SuperType)与派生类(SubType)之间的继承。在派生类的constructor中调用super()即可访问基类的构造函数。super()负责初始化this,相当于ES5中的call和apply方法。
super(name)
console.log(this.name)
}
run(){ // 方法重写
// 调用父类方法
return `喵, ${super.run()}`
}
}
const maomao = new Cat('小臭猫')
console.log(maomao.run())
// 静态属性与方法,不需要new实例化,可以直接调用
console.log(Cat.categories)
~~~
为什么要有 **静态属性** 或 **静态方法**呢,因为 **Class 类里面的定义和实例状态没有太大的关系 。**
>[success] ## Typescript 中的类
**Typescript** 中增强了 **Class 类** ,分别是 **Public、 Private、 Protected、 readonly** ,有了这 **4 种修饰符** ,我们就可以 **给类上的方法和属性提供权限管理** ,因为 **有些内容,我们是不愿意暴露给外部使用的** 。
* **Public** : **修饰的属性或方法是共有的,默认使用的属性或方法都是Public**
* **Private** : **修饰的属性或方法是私有的,不能在声明它的类的外部调用**
* **Protected** : **修饰的属性或方法是受保护的,它跟 Private 类似,因为它在子类中是允许被访问的**
* **readonly** : **只读属性,只可以读取,不可以修改**
1. **Public**
**Public** 就没有什么可以讲的了,因为默认就是 **Public**
2. **Private**
下面的 **run 函数** 前面添加了 **private 修饰符**
**class.ts**
~~~
// 基本类(动物基类)
class Animal {
name: string;
constructor(name){
this.name = name
}
private run(){
return `${this.name} 在奔跑`
}
}
// 实例化函数
const snake = new Animal('小狗')
console.log(snake.run())
~~~
如下,执行时就会报错,加了 **private 修饰符** ,就变成了 **私有方法** ,外部不可以访问。
![](https://img.kancloud.cn/2e/b9/2eb998f19f83a08a93d9f18efe35560d_864x410.png)
3. **protected**
**protected 有点像遗产,只有我与我的子女可以访问,其他外部人员都不可以访问**
**class.ts**
~~~
// ---------------------------------------- 1. 封装 -----------------------------
// 基本类(动物基类)
class Animal {
name: string;
constructor(name){
this.name = name
}
protected run(){
return `${this.name} 在奔跑`
}
}
// 实例化函数
const snake = new Animal('小狗')
console.log(snake.run())
// ---------------------------------------- 2. 继承 -----------------------------
// 小狗继承动物这个类(派生类)
class Dog extends Animal {
bark(){
return `${this.name} 在狂吠`
}
}
// 小狗继承了动物这个类的方法
const xiaobao = new Dog('旺财')
console.log(xiaobao.run())
console.log(xiaobao.bark())
// ---------------------------------------- 3. 多态 -----------------------------
// 小猫继承动物这个类(派生类)
class Cat extends Animal {
// 静态方法
static categories = ['mammal']
constructor(name){
// 使用父类的属性,ES6中我们可以通过类,我们使用extends实现基类(SuperType)与派生类(SubType)之间的继承。在派生类的constructor中调用super()即可访问基类的构造函数。super()负责初始化this,相当于ES5中的call和apply方法。
super(name)
console.log(this.name)
}
run(){ // 方法重写
// 调用父类方法
return `喵, ${super.run()}`
}
}
const maomao = new Cat('小臭猫')
console.log(maomao.run())
// 静态属性与方法,不需要new实例化,可以直接调用
console.log(Cat.categories)
~~~
4. **readonly**
有些时候我们希望有些 **属性只能读取不可以修改** ,这时候我们可以使用 **readonly 修饰符**
**class.ts**
~~~
// 基本类(动物基类)
class Animal {
readonly name: string;
constructor(name){
this.name = name
}
protected run(){
return `${this.name} 在奔跑`
}
}
// 实例化函数
const snake = new Animal('小狗')
snake.name = '小明'
console.log(snake.run())
~~~
**修改 name** 就会报错
![](https://img.kancloud.cn/97/96/9796d4f457a1d280a3c16ed7b1c4d059_632x395.png)
- vue 26课
- Vue-cli3.0项目搭建
- Vue-ui 创建cli3.0项目
- Vue-ui 界面详解
- 项目目录详解
- public文件夹
- favicon.ico
- index.html
- src文件夹
- api文件夹
- assets文件夹
- components文件夹
- config文件夹
- directive文件夹
- lib文件夹
- mock文件夹
- mock简明文档
- router文件夹
- store文件夹
- views文件夹
- App.vue
- main.js
- .browserslistrc
- .editorconfig
- .eslintrc.js
- .gitignore
- babel.config.js
- package-lock.json
- package.json
- postcss.config.js
- README.en.md
- README.md
- vue.config.js
- Vue Router
- 路由详解(一)----基础篇
- 路由详解(二)----进阶篇
- Vuex
- Bus
- Vuex-基础-state&getter
- Vuex-基础-mutation&action/module
- Vuex-进阶
- Ajax请求
- 解决跨域问题
- 封装axios
- Mock.js模拟Ajax响应
- 组件封装
- 从数字渐变组件谈第三方JS库使用
- 从SplitPane组件谈Vue中如何【操作】DOM
- 渲染函数和JSX快速掌握
- 递归组件的使用
- 登陆/登出以及JWT认证
- 响应式布局
- 可收缩多级菜单的实现
- vue杂项
- vue递归组件
- vue-cli3.0多环境打包配置
- Vue+Canvas实现图片剪切
- vue3系统入门与项目实战
- Vue语法初探
- 初学编写 HelloWorld 和 Counter
- 编写字符串反转和内容隐藏功能
- 编写TodoList功能了解循环与双向绑定
- 组件概念初探,对 TodoList 进行组件代码拆分
- Vue基础语法
- Vue 中应用和组件的基础概念
- 理解 Vue 中的生命周期函数
- 常用模版语法讲解
- 数据,方法,计算属性和侦听器
- 样式绑定语法
- 条件渲染
- 列表循环渲染
- 事件绑定
- 表单中双向绑定指令的使用
- 探索组件的理念
- 组件的定义及复用性,局部组件和全局组件
- 组件间传值及传值校验
- 单向数据流的理解
- Non-Props 属性是什么
- 父子组件间如何通过事件进行通信
- 组件间双向绑定高级内容
- 使用匿名插槽和具名插槽解决组件内容传递问题
- 作用域插槽
- 动态组件和异步组件
- 基础语法知识点查缺补漏
- Vue 中的动画
- 使用 Vue 实现基础的 CSS 过渡与动画效果
- 使用 transition 标签实现单元素组件的过渡和动画效果
- 组件和元素切换动画的实现
- 列表动画
- 状态动画
- Vue 中的高级语法
- Mixin 混入的基础语法
- 开发实现 Vue 中的自定义指令
- Teleport 传送门功能
- 更加底层的 render 函数
- 插件的定义和使用
- 数据校验插件开发实例
- Composition API
- Setup 函数的使用
- ref,reactive 响应式引用的用法和原理
- toRef 以及 context 参数
- 使用 Composition API 开发TodoList
- computed方法生成计算属性
- watch 和 watchEffect 的使用和差异性
- 生命周期函数的新写法
- Provide,Inject,模版 Ref 的用法
- Vue 项目开发配套工具讲解
- VueCLI 的使用和单文件组件
- 使用单文件组件编写 TodoList
- Vue-Router 路由的理解和使用
- VueX 的语法详解
- CompositionAPI 中如何使用 VueX
- 使用 axios 发送ajax 请求
- Vue3.0(正式版) + TS
- 你好 Typescript: 进入类型的世界
- 什么是 Typescript
- 为什么要学习 Typescript
- 安装 Typescript
- 原始数据类型和 Any 类型
- 数组和元组
- Interface- 接口初探
- 函数
- 类型推论 联合类型和 类型断言
- class - 类 初次见面
- 类和接口 - 完美搭档
- 枚举(Enum)
- 泛型(Generics) 第一部分
- 泛型(Generics) 第二部分 - 约束泛型
- 泛型第三部分 - 泛型在类和接口中的使用
- 类型别名,字面量 和 交叉类型
- 声明文件
- 内置类型
- 总结