一、如果要生成一个对象实例,需要先定义一个构造函数,然后通过new操作符来完成。
1.普通function创建类
function Person(name, age) {
this.name = name;
this.age = age;
}
// 静态属性
Person.info = 'aaa';
// 实例方法
Person.prototype.say = function () {
console.log('这是Person的实例方法')
}
// 静态方法
Person.show = function () {
console.log('这是Person的静态show方法')
}
const p1 = new Person('王多多', 18);
// 执行上面一行代码,做了几件事?三件
// 1. new Person表示在堆上创建了一个内存; 2. 把'王多多', 18挂载到内存上去; 3.把这个内存的指针引用交给p1
// 构造函数生成实例的执行过程:
// 1.当使用了构造函数,并且new 构造函数(),后台会隐式执行new Object()创建对象;
// 2.将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new
// Object()出来的对象。
// 3.执行构造函数的代码。
// 4.返回新对象(后台直接返回);
console.log(p1);
// 通过new出来的实例,访问到的属性,叫做 【实例属性】
console.log(p1.name);
console.log(p1.age);
p1.say();
// 【静态属性】:通过 构造函数,直接访问到的属性,叫做静态属性
console.log(p1.info); // undefined
console.log(Person.info); // aaa
// 【静态方法】
p1.show(); // 报错
Person.show(); // 这是Person的静态show方法
二、通过class关键字可以定义类
注意项:
1.在类中声明方法的时候,千万不要给该方法加上function关键字;
2.方法之间不要用逗号分隔,否则会报错
// 创建了一个动物类
// 注意1:在class的 {} 区间内,只能写 构造器、静态方法和静态属性、实例方法
// 注意2: class 关键字内部,还是用原来的配方实现的,所以说,我们把class关键字,称作语法糖(用起来比较方便,看的比较顺眼,但是本质未被改变,还是用function实现的)
class Animal {
// 这是类中的 构造器
// 每一个类中,都有一个构造器,如果我们程序员没有手动指定构造器,那么,可以认为类内部
// 有个隐形的、看不见的 空构造器,类似于 construct (){}
// 构造器的作用,就是,每当new这个类的时候,必然会优先执行 构造器中的代码
constructor(name, age) {
// 实例属性
this.name = name;
this.age = age;
}
// 在class内部,通过 static 修饰的属性,就是静态属性
static info = 'eee'
// 这是动物的实例方法
eat() {
console.log('动物的实例方法')
}
// 这是动物 类的静态方法
static show() {
console.log('这是Animal的静态show方法')
}
}
const a1 = new Animal('大黄', 3);
console.log(a1)
// 实例属性
console.log(a1.name)
console.log(a1.age)
// info是Animal的静态属性
console.log(a1.info); // undefined
console.log(Animal.info); // eee
// 这是动物的实例方法
a1.eat()
// 【静态方法】
a1.show(); // 报错
Animal.show(); // 这是Animal的静态show方法
// hasOwnProperty()函数用于判断属性是否是实例属性。其结果是一个布尔值, true说明是实例属性,false说明不是实例属性。
console.log(a1.hasOwnProperty("name")); // true
console.log(a1.hasOwnProperty("age")); // true
console.log(a1.hasOwnProperty("eat")); // false
三、class继承
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
say() {
return name+age;
}
}
// 在class类中,可以使用extends关键字,实现 子类继承父类
// 语法 : class 子类 extends 父类 {}
class American extends Person {
constructor() {
// 问题1: 为什么一定要在constructor 中调用super
// 答:因为如果一个子类,通过extends关键字继承了父类,那么在子类的constructor构造函数中,必须优先调用一下super()
// 问题2: super是个什么东西?
// 答:super是一个函数,而且它是父类的构造器;子类中的super,其实就是父类中,constructor构造器的一个引用
// 问题3: 为什么调用了super()之后,a1实例的name和age都变成undefined了?
// 答:调用super(),相当于调用父类constructor构造器,因为没传值,所以都为undefined
super()
}
// 正确写法
constructor(name, age) {
super(name, age)
}
}
const a1 = new American('jack', 20);
class Chinese extends Person {
// 正确写法
constructor(name, age, personNumber) {
super(name, age)
// 语法规范:在子类中,this只能放在super之后调用
this.personNumber = personNumber
}
}
const a2 = new Chinese('张三', 30, 360202198905108888);