类
什么是类
在js中,类的本质就是一个函数,是基于原型的语法糖,底层仍然是函数和原型链,因为JavaScript采用基于原型的面向对象模式,与传统基于类的语言有所不同,导致它并不像传统的面向对象一样,但是js为了也有这样的一个概念所以搞出来了一个跟类相似的东西,ES6引入的class关键字让面向对象编程更直观,但底层机制不变
// 类本质是函数
class Dog{}
console.log(typeof Dog); // "function"
console.log(Dog.prototype.constructor === Dog); // true
类和对象之间的关系
类:类是一个抽象的概念,比如在生活中,我们常常把所有的狗统一都叫狗,那么狗就是一个类,而所有的狗都有眼睛嘴巴鼻子尾巴之类的共同特征,我们将其称作实例属性,与之对应的,每个狗都会汪汪叫,都会摇尾巴,而这种行为叫做实例方法。
对象:对象是一个具体的实例,比如你自己有一个狗狗,它的名字叫旺财,7岁了,这个就是一个具体的对象。
关系:类是对象的模板,对象是类的实例。
类的实例属性和方法怎么定义
定义实例属性分为两种情况:
- 会变的:还是以狗类为例,当我们将这个类实例化的时候,每个狗的名字、年龄、毛发、性别都会不一样,所以对于这种我们需要用到“constructor” constructor:当我们创建一个实例化对象的时候,类会自动执行这个函数,在这里我们通常会进行一些数据的初始化操作,如果没有进行任何操作,类也会自动帮我们调用这个函数
class Dog{
name="";
age="";
sex="";
hair="";
constructor(name,age,sex,hair){
this.name=name;
this.age=age;
this.sex=sex;
this.hair=hair;
}
cry(){
console.log("汪汪汪");
}
cry2=function(){
console.log("汪汪");
}
}
let wangCai = new Dog("旺财", 8, "公", "光泽亮滑");
console.log(wangCai);
这里需要注意,这两个方法的创建不止止是形式上的区别:
看出来了吗,我们的cry2是直接挂载在自身上的,而cry是挂载在原型上的,所以这里建议类中的方法都用 “方法名(){}” 来定义
- 不会变的:直接赋值就行了
class Dog{
name="旺财";
age=20;
...
}
类的静态属性和方法怎么定义
在js中静态属性是指直接定义在类本身上的属性,而不是定义在实例对象上的属性,静态属性用 static 关键字来声明,并且只能通过类本身来访问
//定义
class Dog{
static name="狗";
static cry(){
console.log("汪汪汪");
}
}
// 使用
console.log(Dog.name);
Dog.cry();
es6类的继承
继承:一个子类继承一个父类(基类) 优点: 1. 子类会拥有父类的所有属性和方法 2. 能重复利用父类中的所有代码
例子:还是以我们的狗来举例,世界上的所有狗狗都可以叫狗,但是狗还有品种之间的区别,有柯基、哈士奇、边牧、拉布拉多等等,这个时候就可以以狗为基类,不同品种的狗为子类来创建一条狗
//创建父类(基类)
class Dog {
constructor(name, age) {
this.name = name;
this.age = age
}
cry(){
console.log("汪汪汪");
}
wagTail() {
console.log(`${this.name}开心地摇着尾巴`);
}
}
//创建子类
class Husky extends Dog {
variety = "";
characteristic = "";
breed = "哈士奇";
constructor(variety,characteristic, name, age) {
super(name, age);
this.variety = variety;
this.characteristic = characteristic;
}
// 改写父类的cry方法
cry(){
console.log("嗷呜~~~");
}
// 哈士奇特有的拆家技能
destroyFurniture() {
console.log(`${this.name}正在疯狂拆家!`);
}
}
// 创建哈士奇实例
let husky = new Husky("哈士奇","中等体型的犬种,身体修长,毛发浓密,颜色通常为黑色、白色、灰色、银色等,是一种非常活泼、好动的狗狗,需要大量的运动和刺激", "旺财", 8)
console.log(husky);
// 访问属性
console.log("名字:", husky.name);
console.log("品种:", husky.breed);
console.log("特征:", husky.characteristic);
// 调用方法
husky.cry();
husky.wagTail();
husky.destroyFurniture();
在面向对象的思想中,有三大特征--封装、继承、多态。而类的继承是面向对象编程的核心,在这个例子中,他让子类能够:
- 继承父类的所有特征:就像小狗天生就会摇尾巴,会汪汪叫
- 添加专属特征:不同品种的狗狗有独特的外貌和性格
- 改写父类行为:哈士奇有独特的“狼嚎”,而非普通的犬吠
继承的三大核心优势:
- 代码复用:不再重复编写基础代码,父类的所有属性和方法自动传承个子类
- 功能扩展自由:子类可以添加专属特征,让每个“品种”都有不同的特征
- 多态灵活:重写父类方法,让不同子类对同一指令做出不同响应
es5之前的继承
在es6“class”关键字出来之前,js都是通过构造函数来模仿类,下面将通过简单的代码来实现一下(了解一下就够了)
// 定义父类构造函数
function Dog(name, age) {
this.name = name;
this.age = age;
}
// 在原型上添加方法,实现所有实例共享
Dog.prototype.cry = function () {
console.log("汪汪汪");
}
Dog.prototype.wagTail = function () {
console.log(this.name + "开心地摇着尾巴");
}
// 定义子类构造函数
function Husky(variety, characteristic, name, age) {
// 调用父类构造函数 (继承属性)
Dog.call(this, name, age);
// 子类特有属性
this.variety = variety;
this.characteristic = characteristic;
this.breed = "哈士奇";
}
// 建立原型链 (继承方法)
Husky.prototype = Object.create(Dog.prototype);
// 修复constructor指向
Husky.prototype.constructor = Husky;
// 添加子类特有方法
Husky.prototype.destroyFurniture = function () {
console.log(this.name + "正在疯狂拆家!");
};
// 重写父类方法
Husky.prototype.cry = function () {
console.log("嗷呜~~~");
};
// 创建哈士奇实例
let husky = new Husky(
"哈士奇",
"中等体型的犬种,身体修长,毛发浓密,颜色通常为黑色、白色、灰色银色等,是一种非常活泼、好动的狗狗,需要大量的运动和刺激",
"旺财",
8
);
console.log(husky);
// 访问属性
console.log("名字:", husky.name);
console.log("品种:", husky.breed);
console.log("特征:", husky.characteristic);
// 调用方法
husky.cry();
husky.wagTail();
husky.destroyFurniture();