简介
传统的Javascript中生成实例是通过构造函数,例如:
//构造函数
function Person(name, sex) {
this.name = name;
this.sex = sex;
}
//原型上的方法
Person.prototype.sayName = function() {
return this.name +', '+this.sex;
}
//生成实例对象
var man = new Person('小明', '男');
由于这种写法和传统的面向对象语言差异很大,所以ES6为了更加接近传统语言的写法,引入了Class(类)的概念,作为对象的模板。通过 class 关键字定义类。
而ES6的class可以当做是一个语法糖,它的绝大部分功能ES5都能做到,新的class写法只是为了让对象原型的写法更加清晰,更加接近传统语言的写法。上面的代码用ES6的class改写之后如下:
//定义类
class Person{
//构造函数
constructor(name, sex) {
this.name = name;
this.sex = sex;
}
//定义原型上的方法
sayName() {
return this.name +', '+this.sex;
}
}
//生成实例对象
let man = new Person('小明', '男');
可以很清楚的看到,定义的类当中同样有一个constructor方法,而这个就是构造方法,其中的this指向生成的实例对象,而类的原型上的构造方法指向“类”本身(例子中就是Person.prototype.constructor === Person)。也就是ES5中的构造函数Person对应着ES6中的构造方法。此外,原来写在原型上的方法现在直接写在类中,这其实就是在给Person.prototype上加方法。而且在生成实例的时候使用的也是new操作符,和构造函数用法其实是一样的。
另外就是在实例上调用类的方法其实就是在调用类原型上的方法,即实例继承了类原型上的方法。
小结
- ES6的class中constructor对应着原来的构造函数
- 类里的普通方法其实就是在构造函数的prototype上定义的方法
- 使用new操作符生成实例。
constructor方法
- constructor是类的默认方法,在new一个对象的时候自动执行,一个类必须有construct方法,如果没有显示的定义也会默认添加一个空的constructor。
- constructor默认返回实例对象(即this)。
- 类必须要用new调用,否则会报错,这是它跟普通构造函数的一个主要区别。
类的实例对象
- 类的实例对象必须用new命令,否则的话会报错。
- 实例的属性除非显示的定义在其本身(this),否则都是定义在原型(类)上。
- 类的所有实例共享一个原型对象(类),这也意味着可以通过__proto__属性给类加方法,但是并不支持,因为这会影响到其它实例。
Class表达式
可以使用表达式的形式定义类,例如:
const Person = class human {
getName() {
return human.name;
}
}
用上述表达式定义的一个类,类名为Person而不是human,human只是在Class内部代码可用,指代当前类,如下:
let man = new Person();
man.getName(); //human
human.name //ReferenceError: human is not defined
如果类中用不到human的话可以省略,如下所示:
const Person = class {/*...*/};
也可以利用Class表达式写出立执行的类,如下。
//开始就使用new操作符生成该类实例
let man = new class{
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}('小明'); //传入参数
person.sayName(); //"小明"
不存在变量提升
变量提升就是不会把类的声明提到代码之前,这是为了保证继承。
静态方法
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
- 不能被实例继承,但是可以被子类继承。
- 直接通过类调用或者通过super对象调用。
- 静态方法中的this指向的是类而不是实例。
Class的静态属性和实例属性
静态属性
class Foo {
//...
}
Foo.prop = 1; //1.给Foo类添加静态属性
//或者
class Foo {
static prop = 1;//2.通过static关键字直接显示添加静态属性
}
实例属性
class Foo {
constuctor() {
this.prop = 1;//1.通过写在构造方法中添加实例属性
}
}
class Foo{
prop = 1;//2.直接通过等式加入实例属性
constructor(){
//...
}
}
new.target属性
一般用在构造函数中,返回new作用的那个构造函数,如果构造函数不是通过new调用的,返回undefined。
- Class内部调用new.target返回当前Class
- 子类继承父类时,返回子类