传统面向对象的编程序语言都是【类】的概念,对象都是由类创建出来,而早期 JavaScript 中是没有类的,面向对象大多都是基于构造函数和原型实现的,但是 ECMAScript 6 规范开始增加了【类】相关的语法,使得 JavaScript 中的面向对象实现方式更加标准
a.认识Class
类可以看做是对象的模板,用一个类可以创建出许多不同的对象
类名一般首字母大写
语法:class 类名 {}
// 创建类
class Person{
// 此处编写封装逻辑
}
class Person {}
// 实例化类
let re = new Person();
console.log(re);
let o = new Person();
console.log(o);
class Dog {}
let d = new Dog();
示例:
总结:
关键字 class
封装了所有的实例属性和方法
类中封装的并不是变量和函数,因此不能使用关键字 let
、const
或 var
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法
一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加
class Point {
}
// 等同于
class Point {
constructor() {}
}
constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象
类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行
总结:
constructor
是类中固定的方法名
constructor
方法在实例化时立即执行
constructor
方法接收实例化时传入的参数
constructor
并非是类中必须要存在的方法
类:
//类
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); //类也可以在其圆形上找到该方法
构造函数:
a.声明形式
class Person {
constructor() {}
speak() {}
}
b.表达式形式
const Person = class {
constructor() {
console.log('constructor');
}
speak() {}
};
new Person();
c.立即执行的匿名类
new(class {
constructor() {
console.log('constructor');
}
})();
与 ES5 一样,在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为
class MyClass {
constructor() {
// ...
}
get prop() {
return 'getter';
}
set prop(value) {
console.log('setter: ' + value);
}
}
let inst = new MyClass();
inst.prop = 123;
// setter: 123
inst.prop
// 'gette
a.实例属性
方法就是值为函数的特殊属性
class Person {
//设置默认属性
age = 14;
name = 'zhangsan';
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);
b.静态方法和静态属性
类相当于实例的原型,所有在类中定义的方法,都会被实例继承
如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”
静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性
总结:
static
关键字用于声明静态属性和方法
静态属性和方法直接通过类名进行访问
a.为什么需要私有属性和方法
私有方法和私有属性,是只能在类的内部访问的方法和属性,外部不能访问
一般情况下,类的属性和方法都是公开的
公有的属性和方法可以被外界修改,造成意想不到的错误
示例:
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);
b.模拟私有属性和方法
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.将私有属性和方法移出类(具有很强的约束力)
一种简单的继承:
//一种简单的继承,通过拷贝其原型来实现
var lynkCoProtype = {
model: "领克",
getModel: function() {
console.log("车辆模具是:" + this.model);
}
};
var volvo = Object.create(lynkCoProtype, {
model: {
value: "沃尔沃"
}
});
volvo.getModel();
子类继承父类
注意:
子类必须在constructor方法中调用super方法,否则新建实例时会报错
这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法
如果不调用super方法,子类就得不到this对象
在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错--这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例
改写继承的属性或方法
super这个关键字,既可以当作函数使用,也可以当作对象使用,就是用来调用父类的方法或属性
在继承的过程中子类中 constructor
中必须调 super
函数,否则会有语法错误
a.作为函数调用
代表父类的构造方法,只能用在子类的构造方法中,用在其他地方就会报错
super 虽然代表了父类的构造方法,但是内部的 this 指向子类的实例
b.作为对象使用
b.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');
}
}
new Programmer();
b.2.在静态方法中使用:
指向父类,而不是父类的原型对象
通过 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');
}
static speak() {
super.speak();
console.log('Programmer speak');
}
}
// new Person();
// new Programmer();
Programmer.speak();
c.注意事项
使用 super 的时候,必须显式指定是作为函数还是作为对象使用,否则会报错