简介
JavaScript
作为一门弱类型的解释性语言,其既可以满足面向对象编程的需要,也可以实践函数式编程范式。随着ES
版本的演进,JavaScript
的功能越来越丰富,书写起来也越来越舒服。其中ES6
新增的Class
语法也使得JavaScript
与传统的面向对象语言越来越相似。ES6
的class
可以看作只是一个语法糖,它的绝大部分功能,ES5
都可以做到,新的class
写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
// 分别使用ES5和ES6语法实现创建对象
function PersonES5(name, age) {
this.name = name;
this.age = age;
}
PersonES5.prototype.walk = function() {
console.log(`${this.name} can walk!`);
}
class PersonES6 {
constructor(name, age) {
this.name = name;
this.age = age;
}
walk() {
console.log(`${this.name} can walk!`);
}
}
console.dir(PersonES6);
console.log(`PersonES6 type is: ${typeof PersonES6}`);
输出结果如下:
由此可见Class
类型仍然是函数,构造函数的prototype
属性仍然在Class
上继续存在。而且类的所有方法都定义在prototype
属性上面。因此,我们通过Class
创建自定定义的对象,调用方法都是在原型上,为所有的实例提供共享使用。
默认方法 constructor
一个class
必须有constructor
方法,如果类中没有定义constructor
方法,默认会添加一个空的constructor
方法。constructor
是class
的默认方法,通过new
操作符创建对象时,默认调用该方法。该方法如果没有指定返回的对象,默认返回的this
实例。constructor
方法在一定范围内可以类比与ES5
中的构造函数,只是构造函数也可以当成函数使用,而构造函数不可以。
function PersonES5(name) {
this.name = name;
}
class PersonES6 {
constructor(name) {
this.name = name;
}
}
存取值函数
class
可以定义getter
和setter
函数,对类型的某一属性进行代理拦截。ES5
中也是有getter
和setter
函数的,其最广泛的应用可能是在Vue2
中通过将data
定义的数据属性使用Object.defineProperty
转换成访问器属性,也就是利用了getter
和setter
函数,从而实现响应式。
class PersonES6 {
constructor(name, age) {
this.name = name;
this.age = age;
}
get prop() {
return 'prop';
}
set prop(val) {
console.log(`new value is: ${val}`);
}
}
静态方法
class
通过static
关键字,定义静态方法。静态方法只能通过class
直接调用,不会被实例继承。
class PersonES6 {
constructor(name, age) {
this.name = name;
this.age = age;
}
walk() {
console.log(`${this.name} can walk!`);
}
static say() {
console.log(`class name is: ${PersonES6.name}`);
}
}
PersonES6.say();
const person = new PersonES6('Jam', 27);
console.dir(PersonES6);
console.dir(person);
输出结果如下:
静态方法在ES5
中实现即是将方法直接挂在构造函数上。
function PersonES5(name, age) {
this.name = name;
this.age = age;
}
PersonES5.prototype.walk = function() {
console.log(`${this.name} can walk!`);
}
PersonES5.say = function() {
console.log(`class name is: ${PersonES5.name}`);
}
PersonES5.say();
const person = new PersonES5('Jam', 27);
console.dir(PersonES5);
console.dir(person);
输出结果如下:
继承
Class
可以通过关键字extends
实现继承,比ES5
(ES5
继承参见博客:JavaScript基础:继承)中修改原型链实现继承要方便很多。
class Parent() {
constructor(name) {
this.name = name;
}
}
class Son extends Parent() {
constructor(name, age) {
super(name);
this.name = name;
}
}
super 关键字
super
既可以当作函数使用,也可以被当作对象使用。在子类的constructor
方法中,调用super
是当作函数使用,实例化this
对象。super
作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
class Parent {
constructor(name) {
this.name = name;
}
say() {
console.log(`name is: ${this.name}`);
}
static say() {
console.log(`parent name is: ${this.name}`);
}
}
class Son extends Parent {
constructor(name, age) {
super(name);
this.age = age;
}
sayName() {
super.say();
}
static sayName() {
super.say();
}
}
Son.sayName();
const son = new Son('Jam', 27);
son.sayName();
输出结果如下:
需要注意的是在子类普通方法中通过super
调用父类的方法时,方法内部的this
指向当前的子类实例。子类的静态方法中通过super
调用父类的方法时,方法内部的this
指向当前的子类。