Vue 面试题
1.Vue 双向绑定原理
2.描述下 vue 从初始化页面–修改数据–刷新页面 UI 的过程?
3.你是如何理解 Vue 的响应式系统的?
4.虚拟 DOM 实现原理
5.既然 Vue 通过数据劫持可以精准探测数据变化,为什么还需要虚拟 DOM 进行 diff 检测差异?
6.Vue 中 key 值的作用?
7.Vue 的生命周期
8.Vue 组件间通信有哪些方式?
9.watch、methods 和 computed 的区别?
10.vue 中怎么重置 data?
11.组件中写 name 选项有什么作用?
12.vue-router 有哪些钩子函数?
13.route 和 router 的区别是什么?
14.说一下 Vue 和 React 的认识,做一个简单的对比
15.Vue 的 nextTick 的原理是什么?
16.Vuex 有哪几种属性?
17.vue 首屏加载优化
18.Vue 3.0 有没有过了解?
19.vue-cli 替我们做了哪些工作?
如果你觉得对你有帮助,可以戳这里获取:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
“compilerOptions”: {
“module”: “CommonJS”
}
/‘none’, ‘commonjs’, ‘amd’, ‘system’, ‘umd’, ‘es6’, ‘es2015’, ‘es2020’, ‘es2022’, ‘esnext’, ‘node12’, ‘nodenext’/
outDir
-
编译后文件的所在目录
-
默认情况下,编译后的js文件会和ts文件位于相同的目录,设置outDir后可以改变编译后文件的位置
-
示例:
“compilerOptions”: {
“outDir”: “dist”
}
- 设置后编译后的js文件将会生成到dist目录
outFile
-
将所有的文件编译为一个js文件
-
默认会将所有的编写在全局作用域中的代码合并为一个js文件,如果module制定了None、System或AMD则会将模块一起合并到文件之中
-
一般不会用这个,一般用打包工具
-
示例:
“compilerOptions”: {
“outFile”: “dist/app.js”
}
rootDir
-
指定代码的根目录,默认情况下编译后文件的目录结构会以最长的公共目录为根目录,通过rootDir可以手动指定根目录
-
示例:
“compilerOptions”: {
“rootDir”: “./src”
}
allowJs
- 是否对js文件编译 ,默认是false
checkJs
-
是否对js文件进行检查
-
是否检查js代码是否符合ts语法规范,默认是false
-
示例:
“compilerOptions”: {
“allowJs”: true,
“checkJs”: true
}
removeComments
-
是否删除注释
-
默认值:false
noEmit
-
不对代码进行编译
-
不生成编译后的文件
-
只想检查语法的时候可能用
-
默认值:false
noEmitOnError
-
有错误的情况下不进行编译
-
默认值:false
sourceMap
-
是否生成sourceMap
-
默认值:false
严格检查
-
strict
-
启用所有的严格检查,默认值为true,设置后相当于开启了所有的严格检查
-
alwaysStrict
-
总是以严格模式对代码进行编译
-
noImplicitAny
-
禁止隐式的any类型
-
noImplicitThis
-
禁止类型不明确的this
-
strictBindCallApply
-
严格检查bind、call和apply的参数列表
-
strictFunctionTypes
-
严格检查函数的类型
-
strictNullChecks
-
严格的空值检查
let box1 = document.getElementById(‘box1’);
// if(box1 !== null){
// box1.addEventListener(‘click’, function (){
// alert(‘hello’);
// });
// }
box1?.addEventListener(‘click’, function (){
alert(‘hello’);
});
-
strictPropertyInitialization
-
严格检查属性是否初始化
额外检查
-
noFallthroughCasesInSwitch
-
检查switch语句包含正确的break
-
noImplicitReturns
-
检查函数没有隐式的返回值
-
noUnusedLocals
-
检查未使用的局部变量
-
noUnusedParameters
-
检查未使用的参数
高级
-
allowUnreachableCode
-
检查不可达代码
-
可选值:
-
true,忽略不可达代码
-
false,不可达代码将引起错误
-
noEmitOnError
-
有错误的情况下不进行编译
-
默认值:false
- 通常情况下,实际开发中我们都需要使用构建工具对代码进行打包,TS同样也可以结合构建工具一起使用,下边以webpack为例介绍一下如何结合构建工具使用TS。
步骤:
- 初始化项目
-
进入项目根目录,执行命令
npm init -y
-
主要作用:创建package.json文件
- 下载构建工具
-
npm i -D webpack webpack-cli webpack-dev-server typescript ts-loader clean-webpack-plugin
-
共安装了7个包
-
webpack
-
构建工具webpack
-
webpack-cli
-
webpack的命令行工具
-
webpack-dev-server
-
webpack的开发服务器
-
typescript
-
ts编译器
-
ts-loader
-
ts加载器,用于在webpack中编译ts文件
-
html-webpack-plugin
-
webpack中html插件,用来自动创建html文件
-
npm i -D html-webpack-plugin
-
clean-webpack-plugin
-
webpack中的清除插件,每次构建都会先清除目录
- 根目录下创建webpack的配置文件webpack.config.js
// 引入一个包
const path = require(“path”);
// 引入html插件
const HtmlWebpackPlugin = require(“html-webpack-plugin”);
// 引入clean插件
const { CleanWebpackPlugin } = require(“clean-webpack-plugin”);
// webpack中的所有的配置信息都应该写在module.exports中
module.exports = {
optimization:{
minimize: false // 关闭代码压缩,可选
},
// 指定入口文件
entry: “./src/index.ts”,
// 指定打包文件所在目录
output: {
// 指定打包文件的目录
path: path.resolve(__dirname, “dist”),
// 打包后文件的文件
filename: “bundle.js”,
},
// 用来设置引用模块
resolve: {
extensions: [“.ts”, “.js”]
},
// 指定webpack打包时要使用模块
module: {
// 指定要加载的规则
rules: [
{
// test指定的是规则生效的文件
test: /.ts$/,
// 要使用的loader
use: {
loader: “ts-loader”
},
// 要排除的文件
exclude: /node_modules/
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
//title:‘TS测试’
template: “./src/index.html”//设定模板
}),
],
mode:‘production’
}
- 根目录下创建tsconfig.json,配置可以根据自己需要
{
“compilerOptions”: {
“target”: “ES2015”,
“module”: “ES2015”,
“strict”: true
}
}
- 修改package.json添加如下配置
{
…略…
“scripts”: {
“test”: “echo “Error: no test specified” && exit 1”,
“build”: “webpack”,
“start”: “webpack serve --open chrome.exe”
},
…略…
}
- 在src下创建ts文件,并在并命令行执行
npm run build
对代码进行编译,或者执行npm start
来启动开发服务器
- 经过一系列的配置,使得TS和webpack已经结合到了一起,除了webpack,开发中还经常需要结合babel来对代码进行转换以使其可以兼容到更多的浏览器,在上述步骤的基础上,通过以下步骤再将babel引入到项目中。
- 安装依赖包:
-
npm i -D @babel/core @babel/preset-env babel-loader core-js
-
共安装了4个包,分别是:
-
@babel/core
-
babel的核心工具
-
@babel/preset-env
-
babel的预定义环境
-
@babel-loader
-
babel在webpack中的加载器
-
core-js
-
core-js用来使老版本的浏览器支持新版ES语法
- 修改webpack.config.js配置文件
// 引入一个包
const path = require(‘path’);
// 引入html插件
const HTMLWebpackPlugin = require(‘html-webpack-plugin’);
// 引入clean插件
const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’);
// webpack中的所有的配置信息都应该写在module.exports中
module.exports = {
// 指定入口文件
entry: “./src/index.ts”,
// 指定打包文件所在目录
output: {
// 指定打包文件的目录
path: path.resolve(__dirname, ‘dist’),
// 打包后文件的文件
filename: “bundle.js”,
// 告诉webpack不使用箭头//webpack会生成箭头函数的立即执行函数,这里不让他使用箭头函数
environment:{
arrowFunction: false
}
},
// 指定webpack打包时要使用模块
module: {
// 指定要加载的规则
rules: [
{
// test指定的是规则生效的文件
test: /.ts$/,
// 要使用的loader
use: [
// 配置babel
{
// 指定加载器
loader:“babel-loader”,
// 设置babel
options: {
// 设置预定义的环境
presets:[
[
// 指定环境的插件
“@babel/preset-env”,
// 配置信息
{
// 要兼容的目标浏览器
targets:{
“chrome”:“58”,
“ie”:“11”
},
// 指定corejs的版本//因为这里下载的是"core-js": “^3.21.1”,
“corejs”:“3”,
// 使用corejs的方式 “usage” 表示按需加载
“useBuiltIns”:“usage”
}
]
]
}
},
‘ts-loader’
],
// 要排除的文件
exclude: /node-modules/
}
]
},
// 配置Webpack插件
plugins: [
new CleanWebpackPlugin(),
new HTMLWebpackPlugin({
// title: “这是一个自定义的title”
template: “./src/index.html”
}),
],
// 用来设置引用模块
resolve: {
extensions: [‘.ts’, ‘.js’]
},
mode:‘production’
};
- 如此一来,使用ts编译后的文件将会再次被babel处理,使得代码可以在大部分浏览器中直接使用,可以在配置选项的targets中指定要兼容的浏览器版本。
面向对象是程序中一个非常重要的思想,它被很多同学理解成了一个比较难,比较深奥的问题,其实不然。面向对象很简单,简而言之就是程序之中所有的操作都需要通过对象来完成。
-
举例来说:
-
操作浏览器要使用window对象
-
操作网页要使用document对象
-
操作控制台要使用console对象
一切操作都要通过对象,也就是所谓的面向对象,那么对象到底是什么呢?这就要先说到程序是什么,计算机程序的本质就是对现实事物的抽象,抽象的反义词是具体,比如:照片是对一个具体的人的抽象,汽车模型是对具体汽车的抽象等等。程序也是对事物的抽象,在程序中我们可以表示一个人、一条狗、一把枪、一颗子弹等等所有的事物。一个事物到了程序中就变成了一个对象。
在程序中所有的对象都被分成了两个部分数据和功能,以人为例,人的姓名、性别、年龄、身高、体重等属于数据,人可以说话、走路、吃饭、睡觉这些属于人的功能。数据在对象中被成为属性,而功能就被称为方法。所以简而言之,在程序中一切皆是对象。
1、类(class)
要想面向对象,操作对象,首先便要拥有对象,那么下一个问题就是如何创建对象。要创建对象,必须要先定义类,所谓的类可以理解为对象的模型,程序中可以根据类创建指定类型的对象,举例来说:可以通过Person类来创建人的对象,通过Dog类创建狗的对象,通过Car类来创建汽车的对象,不同的类可以用来创建不同的对象。
- 定义类:
class 类名 {
属性名: 类型;
constructor(参数: 类型){
this.属性名 = 参数;
}
方法名(){
…
}
}
- 示例:
class Person{
name: string;
age: number;
constructor(name: string, age: number){
this.name = name;
this.age = age;
}
sayHello(){
console.log(大家好,我是${this.name}
);
}
}
- 使用类:
const p = new Person(‘孙悟空’, 18);
p.sayHello();
类的简介
// 使用class关键字来定义一个类
/*
-
对象中主要包含了两个部分:
-
属性
-
方法
-
*/
class Person{
/*
-
直接定义的属性是实例属性,需要通过对象的实例去访问:
-
const per = new Person();
-
per.name
-
使用static开头的属性是静态属性(类属性),可以直接通过类去访问
-
Person.age
-
readonly开头的属性表示一个只读的属性无法修改
-
*/
// 定义实例属性
// readonly name: string = ‘孙悟空’;
name = ‘孙悟空’;
// 在属性前使用static关键字可以定义类属性(静态属性)
// static readonly age: number = 18;
age = 18;
// 定义方法
/*
-
如果方法以static开头则方法就是类方法,可以直接通过类去调用
-
*/
sayHello(){
console.log(‘Hello 大家好!’);
}
}
const per = new Person();
per.sayHello();
构造函数
class Dog{
name: string;
age: number;
// constructor 被称为构造函数
// 构造函数会在对象创建时调用
constructor(name: string, age: number) {
// 在实例方法中,this就表示当前当前的实例
// 在构造函数中当前对象就是当前新建的那个对象
// 可以通过this向新建的对象中添加属性
this.name = name;
this.age = age;
}
bark(){
// alert(‘汪汪汪!’);
// 在方法中可以通过this来表示当前调用方法的对象
console.log(this.name);
}
}
const dog = new Dog(‘小黑’, 4);
const dog2 = new Dog(‘小白’, 2);
// console.log(dog);
// console.log(dog2);
dog2.bark();
继承
(function (){
// 定义一个Animal类
class Animal{
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHello(){
console.log(‘动物在叫~’);
}
}
/*
-
Dog extends Animal
-
- 此时,Animal被称为父类,Dog被称为子类
-
- 使用继承后,子类将会拥有父类所有的方法和属性
-
- 通过继承可以将多个类中共有的代码写在一个父类中,
-
这样只需要写一次即可让所有的子类都同时拥有父类中的属性和方法
-
如果希望在子类中添加一些父类中没有的属性或方法直接加就行
-
- 如果在子类中添加了和父类相同的方法,则子类方法会覆盖掉父类的方法
-
这种子类覆盖掉父类方法的形式,我们称为方法重写
-
*/
// 定义一个表示狗的类
// 使Dog类继承Animal类
class Dog extends Animal{
run(){
console.log(${this.name}在跑~~~
);
}
sayHello() {
console.log(‘汪汪汪汪!’);
}
}
// 定义一个表示猫的类
// 使Cat类继承Animal类
class Cat extends Animal{
sayHello() {
console.log(‘喵喵喵喵!’);
}
}
const dog = new Dog(‘旺财’, 5);
const cat = new Cat(‘咪咪’, 3);
console.log(dog);
dog.sayHello();
dog.run();
console.log(cat);
cat.sayHello();
})();
super
(function () {
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log(‘动物在叫~’);
}
}
class Dog extends Animal{
age: number;
constructor(name: string, age: number) {
// 如果在子类中写了构造函数,在子类构造函数中必须对父类的构造函数进行调用
super(name); // 调用父类的构造函数
this.age = age;
}
sayHello() {
// 在类的方法中 super就表示当前类的父类
//super.sayHello();
console.log(‘汪汪汪汪!’);
}
}
const dog = new Dog(‘旺财’, 3);
dog.sayHello();
})();
抽象类
(function () {
/*
-
以abstract开头的类是抽象类,
-
抽象类和其他类区别不大,只是不能用来创建对象
-
抽象类就是专门用来被继承的类
-
抽象类中可以添加抽象方法
-
*/
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
// 定义一个抽象方法
// 抽象方法使用 abstract开头,没有方法体
// 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
abstract sayHello():void;
}
class Dog extends Animal{
sayHello() {
console.log(‘汪汪汪汪!’);
}
}
class Cat extends Animal{
sayHello() {
console.log(‘喵喵喵喵!’);
}
}
const dog = new Dog(‘旺财’);
dog.sayHello();
})();
接口
接口就是定义了一个规范
(function () {
// 描述一个对象的类型
type myType = {
name: string,
age: number
};
/*
-
接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法
-
同时接口也可以当成类型声明去使用
-
*/
interface myInterface {
name: string;
age: number;
}
interface myInterface {
gender: string;
}
// const obj: myInterface = {
// name: ‘sss’,
// age: 111,
// gender: ‘男’
// };
/*
-
接口可以在定义类的时候去限制类的结构,
-
接口中的所有的属性都不能有实际的值
-
接口只定义对象的结构,而不考虑实际值
-
在接口中所有的方法都是抽象方法
-
*/
interface myInter{
name: string;
sayHello():void;
}
/*
-
定义类时,可以使类去实现一个接口,
-
实现接口就是使类满足接口的要求
-
*/
class MyClass implements myInter{
name: string;
constructor(name: string) {
this.name = name;
}
sayHello(){
console.log(‘大家好~~’);
}
}
})();
封装
可以直接将属性定义在构造函数中
(function (){
// 定义一个表示人的类
class Person{
// TS可以在属性前添加属性的修饰符
/*
-
public 修饰的属性可以在任意位置访问(修改) 默认值
-
private 私有属性,私有属性只能在类内部进行访问(修改)
-
- 通过在类中添加方法使得私有属性可以被外部访问
-
protected 受包含的属性,只能在当前类和当前类的子类中访问(修改)
-
*/
private _name: string;
private _age: number;
constructor(name: string, age: number) {
this._name = name;
this._age = age;
}
/*
-
getter方法用来读取属性
-
setter方法用来设置属性
-
- 它们被称为属性的存取器
-
*/
// 定义方法,用来获取name属性
// getName(){
// return this._name;
// }
//
// // 定义方法,用来设置name属性
// setName(value: string){
// this._name = value;
// }
//
// getAge(){
// return this._age;
// }
//
// setAge(value: number){
// // 判断年龄是否合法
// if(value >= 0){
// this._age = value;
// }
// }
// TS中设置getter方法的方式
get name(){
// console.log(‘get name()执行了!!’);
return this._name;
}
set name(value){
this._name = value;
}
get age(){
return this._age;
}
set age(value){
if(value >= 0){
this._age = value
}
}
}
const per = new Person(‘孙悟空’, 18);
/*
-
现在属性是在对象中设置的,属性可以任意的被修改,
-
属性可以任意被修改将会导致对象中的数据变得非常不安全
-
*/
// per.setName(‘猪八戒’);
// per.setAge(-33);
per.name = ‘猪八戒’;
per.age = -33;
// console.log(per);
class A{
protected num: number;
constructor(num: number) {
this.num = num;
}
}
class B extends A{
test(){
console.log(this.num);
}
}
const b = new B(123);
// b.num = 33;//无法访问
/* class C{
name: string;
age: number
// 可以直接将属性定义在构造函数中
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}*/
class C{
// 可以直接将属性定义在构造函数中
constructor(public name: string, public age: number) {
}
}
const c = new C(‘xxx’, 111);
console.log©;
})();
泛型
/*
function fn(a: any): any{
return a;
}*/
/*
-
在定义函数或是类时,如果遇到类型不明确就可以使用泛型
-
*/
function fn(a: T): T{
return a;
}
// 可以直接调用具有泛型的函数
let result = fn(10); // 不指定泛型,TS可以自动对类型进行推断
let result2 = fn(‘hello’); // 指定泛型
// 泛型可以同时指定多个
function fn2<T, K>(a: T, b: K):T{
console.log(b);
return a;
}
fn2<number, string>(123, ‘hello’);
interface Inter{
length: number;
}
// T extends Inter 表示泛型T必须时Inter实现类(子类)
function fn3(a: T): number{
return a.length;
}
class MyClass{
name: T;
constructor(name: T) {
this.name = name;
}
}
const mc = new MyClass(‘孙悟空’);
2、面向对象的特点
1).封装
-
对象实质上就是属性和方法的容器,它的主要作用就是存储属性和方法,这就是所谓的封装
-
默认情况下,对象的属性是可以任意的修改的,为了确保数据的安全性,在TS中可以对属性的权限进行设置
-
只读属性(readonly):
-
如果在声明属性时添加一个readonly,则属性便成了只读属性无法修改
-
TS中属性具有三种修饰符:
-
public(默认值),可以在类、子类和对象中修改
-
protected ,可以在类、子类中修改
-
private ,可以在类中修改
-
示例:
-
public
class Person{
public name: string; // 写或什么都不写都是public
public age: number;
constructor(name: string, age: number){
this.name = name; // 可以在类中修改
this.age = age;
}
sayHello(){
console.log(大家好,我是${this.name}
);
}
}
class Employee extends Person{
constructor(name: string, age: number){
super(name, age);
this.name = name; //子类中可以修改
}
}
const p = new Person(‘孙悟空’, 18);
p.name = ‘猪八戒’;// 可以通过对象修改
- protected
class Person{
protected name: string;
protected age: number;
constructor(name: string, age: number){
this.name = name; // 可以修改
this.age = age;
}
sayHello(){
console.log(大家好,我是${this.name}
);
}
}
class Employee extends Person{
constructor(name: string, age: number){
super(name, age);
this.name = name; //子类中可以修改
}
}
const p = new Person(‘孙悟空’, 18);
p.name = ‘猪八戒’;// 不能修改
- private
class Person{
private name: string;
private age: number;
constructor(name: string, age: number){
this.name = name; // 可以修改
this.age = age;
}
sayHello(){
console.log(大家好,我是${this.name}
);
}
}
class Employee extends Person{
constructor(name: string, age: number){
super(name, age);
this.name = name; //子类中不能修改
}
}
const p = new Person(‘孙悟空’, 18);
p.name = ‘猪八戒’;// 不能修改
-
属性存取器
-
对于一些不希望被任意修改的属性,可以将其设置为private
-
直接将其设置为private将导致无法再通过对象修改其中的属性
-
我们可以在类中定义一组读取、设置属性的方法,这种对属性读取或设置的属性被称为属性的存取器
-
读取属性的方法叫做setter方法,设置属性的方法叫做getter方法
-
示例:
class Person{
private _name: string;
constructor(name: string){
this._name = name;
}
get name(){
return this._name;
}
set name(name: string){
this._name = name;
}
}
const p1 = new Person(‘孙悟空’);
console.log(p1.name); // 通过getter读取name属性
p1.name = ‘猪八戒’; // 通过setter修改name属性
-
静态属性
-
静态属性(方法),也称为类属性。使用静态属性无需创建实例,通过类即可直接使用
-
静态属性(方法)使用static开头
-
示例:
class Tools{
static PI = 3.1415926;
static sum(num1: number, num2: number){
return num1 + num2
}
}
console.log(Tools.PI);
console.log(Tools.sum(123, 456));
-
this
-
在类中,使用this表示当前对象
2)继承
-
继承时面向对象中的又一个特性
-
通过继承可以将其他类中的属性和方法引入到当前类中
-
OCP((Open Closed Principle)) 开闭原则 拓展开放,修改关闭
-
示例:
class Animal{
name: string;
age: number;
constructor(name: string, age: number){
this.name = name;
this.age = age;
}
}
class Dog extends Animal{
bark(){
console.log(${this.name}在汪汪叫!
);
}
}
const dog = new Dog(‘旺财’, 4);
dog.bark();
-
通过继承可以在不修改类的情况下完成对类的扩展
-
重写
-
发生继承时,如果子类中的方法会替换掉父类中的同名方法,这就称为方法的重写
-
示例:
class Animal{
最后
喜欢的话别忘了关注、点赞哦~
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
ge);
this.name = name; //子类中可以修改
}
}
const p = new Person(‘孙悟空’, 18);
p.name = ‘猪八戒’;// 不能修改
- private
class Person{
private name: string;
private age: number;
constructor(name: string, age: number){
this.name = name; // 可以修改
this.age = age;
}
sayHello(){
console.log(大家好,我是${this.name}
);
}
}
class Employee extends Person{
constructor(name: string, age: number){
super(name, age);
this.name = name; //子类中不能修改
}
}
const p = new Person(‘孙悟空’, 18);
p.name = ‘猪八戒’;// 不能修改
-
属性存取器
-
对于一些不希望被任意修改的属性,可以将其设置为private
-
直接将其设置为private将导致无法再通过对象修改其中的属性
-
我们可以在类中定义一组读取、设置属性的方法,这种对属性读取或设置的属性被称为属性的存取器
-
读取属性的方法叫做setter方法,设置属性的方法叫做getter方法
-
示例:
class Person{
private _name: string;
constructor(name: string){
this._name = name;
}
get name(){
return this._name;
}
set name(name: string){
this._name = name;
}
}
const p1 = new Person(‘孙悟空’);
console.log(p1.name); // 通过getter读取name属性
p1.name = ‘猪八戒’; // 通过setter修改name属性
-
静态属性
-
静态属性(方法),也称为类属性。使用静态属性无需创建实例,通过类即可直接使用
-
静态属性(方法)使用static开头
-
示例:
class Tools{
static PI = 3.1415926;
static sum(num1: number, num2: number){
return num1 + num2
}
}
console.log(Tools.PI);
console.log(Tools.sum(123, 456));
-
this
-
在类中,使用this表示当前对象
2)继承
-
继承时面向对象中的又一个特性
-
通过继承可以将其他类中的属性和方法引入到当前类中
-
OCP((Open Closed Principle)) 开闭原则 拓展开放,修改关闭
-
示例:
class Animal{
name: string;
age: number;
constructor(name: string, age: number){
this.name = name;
this.age = age;
}
}
class Dog extends Animal{
bark(){
console.log(${this.name}在汪汪叫!
);
}
}
const dog = new Dog(‘旺财’, 4);
dog.bark();
-
通过继承可以在不修改类的情况下完成对类的扩展
-
重写
-
发生继承时,如果子类中的方法会替换掉父类中的同名方法,这就称为方法的重写
-
示例:
class Animal{
最后
喜欢的话别忘了关注、点赞哦~
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】