简介
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指向当前的子类。