Class类
一、认识Class
1、是什么
1.认识 Class
人类:类
具体的人:实例、对象
类可以看做是对象的模板,用一个类可以创建出许多不同的对象
2、基本用法
2.Class 的基本用法
类名一般大写
class Person {} √
class Person() {} ×
class Person {}; ×
function func() {}
class Person {
// 实例化时执行构造方法,所以必须有构造方法,但可以不写出来
constructor(name, age) {
// console.log('实例化时执行构造方法');
// this 代表实例对象,上面定义的是实例属性/方法
this.name = name;
this.age = age;
// 一般在构造方法中定义属性,方法不在构造方法中定义
// this.speak = () => {};
}
// speak:function(){}
// 各实例共享的方法
speak() {
console.log('speak');
}
}
// Person();
const zs = new Person('ZS', 18);
const ls = new Person('LS', 28);
// console.log(zs.name);
// console.log(zs.age);
// console.log(zs.speak);
zs.speak();
// console.log(ls.name);
// console.log(ls.age);
// console.log(ls.speak);
console.log(zs.speak === ls.speak);
3、Class与构造函数
// 3.Class 与构造函数
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
// this.speak = () => {};
}
speak() {
console.log('speak');
}
// run(){}
}
// Person.prototype.run = function () {};
// console.log(typeof Person);
// console.log(Person.prototype.speak);
// function Person(name, age) {
// this.name = name;
// this.age = age;
// // this.speak = () => {};
// }
// Person.prototype.speak = function () {};
4、Class的两种定义形式
1、声明形式
2、表达式形式
1.声明形式
class Person {
constructor() {}
speak() {}
}
2.表达式形式
function Person(){}
const Person = function () {};
const Person = class {
constructor() {
console.log('constructor');
}
speak() {}
};
new Person();
(function () {
console.log('func');
})();
func()
// 立即执行的匿名类
new (class {
constructor() {
console.log('constructor');
}
})();
// new Person();
二、Class的属性和方法
1.实例属性
方法就是值为函数的特殊属性
class Person {
age = 0;
sex = 'male';
getSex = function () {
return this.sex;
};
constructor(name, sex) {
this.name = name;
// this.age = 18;
this.sex = sex;
}
// speak() {
// this.age = 18;
// }
}
const p = new Person('Alex');
console.log(p.name);
console.log(p.age);
2.静态方法
类的方法
class Person {
constructor(name) {
this.name = name;
}
speak() {
console.log('speak');
console.log(this);
}
// static speak() {
// console.log('人类可以说话');
// // this 指向类
// console.log(this);
// }
}
// Person.speak = function () {
// console.log('人类可以说话');
// console.log(this);
// };
const p = new Person('Alex');
p.speak();
Person.speak();
// 3.静态属性
// 类的属性
class Person {
constructor(name) {
this.name = name;
}
// 不要这么写,目前只是提案,有兼容性问题
// static version = '1.0';
static getVersion() {
return '1.0';
}
}
// Person.version = '1.0';
const p = new Person('Alex');
console.log(p.name);
// console.log(Person.version);
console.log(Person.getVersion());
1.为什么需要私有属性和方法
一般情况下,类的属性和方法都是公开的
公有的属性和方法可以被外界修改,造成意想不到的错误
class Person {
constructor(name) {
this.name = name;
}
speak() {
console.log('speak');
}
getName() {
return this.name;
}
}
const p = new Person('Alex');
console.log(p.name);
p.speak();
// ....
p.name = 'zs';
console.log(p.name);
2.模拟私有属性和方法
2.1._ 开头表示私有
class Person {
constructor(name) {
this._name = name;
}
speak() {
console.log('speak');
}
getName() {
return this._name;
}
}
const p = new Person('Alex');
// console.log(p.name);
p.name = 'zd';
console.log(p.getName());
// 2.2.将私有属性和方法移出类
(function () {
let name = '';
class Person {
constructor(username) {
// this.name = name;
name = username;
}
speak() {
console.log('speak');
}
getName() {
return name;
}
}
window.Person = Person;
})();
(function () {
const p = new Person('Alex');
console.log(p.name);
console.log(p.getName());
})();
三、Class的继承
1、extends
// 1.子类继承父类
class Person {
constructor(name, sex) {
this.name = name;
this.sex = sex;
this.say = function () {
console.log('say');
};
}
speak() {
console.log('speak');
}
static speak() {
console.log('static speak');
}
}
Person.version = '1.0';
// class Programmer extends Person {
// constructor(name, sex) {
// super(name, sex);
// }
// }
// const zs = new Programmer('zs', '男');
// console.log(zs.name);
// console.log(zs.sex);
// zs.say();
// zs.speak();
// Programmer.speak();
// console.log(Programmer.version);
// 2.改写继承的属性或方法
class Programmer extends Person {
constructor(name, sex, feature) {
// this.feature = feature; ×
// this 操作不能放在 super 前面
super(name, sex);
// this.feature = feature;
}
hi() {
console.log('hi');
}
// 同名覆盖
speak() {
console.log('Programmer speak');
}
static speak() {
console.log('Programmer static speak');
}
}
Programmer.version = '2.0';
const zs = new Programmer('zs', '男', '秃头');
console.log(zs.name);
console.log(zs.sex);
console.log(zs.feature);
zs.say();
zs.speak();
zs.hi();
Programmer.speak();
console.log(Programmer.version);
2、super
1.作为函数调用
代表父类的构造方法,只能用在子类的构造方法中,用在其他地方就会报错
super 虽然代表了父类的构造方法,但是内部的 this 指向子类的实例
class Person {
constructor(name) {
this.name = name;
console.log(this);
}
}
class Programmer extends Person {
constructor(name, sex) {
super(name, sex);
}
// hi() {
// super(); // ×
// }
}
// new Person();
new Programmer();
2.作为对象使用
2.1.在构造方法中使用或一般方法中使用
super 代表父类的原型对象 Person.prototype
所以定义在父类实例上的方法或属性,是无法通过 super 调用的
通过 super 调用父类的方法时,方法内部的 this 指向当前的子类实例
class Person {
constructor(name) {
this.name = name;
console.log(this);
}
speak() {
console.log('speak');
// console.log(this);
}
static speak() {
console.log('Person speak');
console.log(this);
}
}
class Programmer extends Person {
constructor(name, sex) {
super(name, sex);
// console.log(super.name);
// super.speak();
}
// hi() {
// super(); // ×
// }
speak() {
super.speak();
console.log('Programmer speak');
}
// 2.2.在静态方法中使用
// 指向父类,而不是父类的原型对象
// 通过 super 调用父类的方法时,方法内部的 this 指向当前的子类,而不是子类的实例
static speak() {
super.speak();
console.log('Programmer speak');
}
}
// new Person();
// new Programmer();
Programmer.speak();
// 3.注意事项
// 使用 super 的时候,必须显式指定是作为函数还是作为对象使用,否则会报错
class Person {
constructor(name) {
this.name = name;
}
speak() {
console.log('speak');
}
}
class Programmer extends Person {
constructor(name, sex) {
super(name, sex);
// console.log(super);
// console.log(super());
// console.log(super.speak);
}
}