ES6中的类
class与构造函数
基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
//类的写法
class Point{
getName(){
return 'lili';
}
}
//构造函数的写法
function Point2() {}
Point2.prototype.getName = function () {
return 'lili';
}
其实class也是函数,类里的方法也是定义在prototype上。类的方法都是不可枚举的,通过Object.keys不能获得,但是构造函数原型上的方法可以获得。
类与构造函数对比
// ES6以前的构造函数
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.eat = function(){
return '('+ this.age + '岁的' + this.name +'正在吃饭...'+')';
}
p1 = new Person('张三',3);
p1.eat();
// ES6的构造函数(类)
class Person{
constructor(name, age){
this.name = name;
this.age = age;
}
eat(){
return '('+ this.age + '岁的' + this.name +'正在吃饭...'+')';
}
}
let p2 = new Person('张三',3);
p1.eat();
- 可以是类在某种意义上就是构造函数的升级版
- constructor:指向的就是Person类的构造函数(就算你不写,JavaScript引擎也会自动添加一个空的)
- 在Person类里面编写的方法就是相当于在Person类的原型上编写
- 类的内部的所有定义的方法,都是不可枚举的
- 类必须通过new关键字调用,否则会报错
静态方法和静态属性
- 属于类,不被实例继承,直接通过类来调用。可以被子类继承
- 内部的this,执行Point本身,而不是实例
- 可以和非静态方法重名
class Point {
static getX() {
this.getY();
}
static getY(){
console.log('y');
}
getY(){
console.log('yy');
}
}
let point = new Point();
Point.getX();
//'y'
私有方法和私有属性
私有方法和私有属性:只能在内部访问,外部不能访问。遗憾的是es6没有面向对象中的私有方法和私有属性
- 第一种方法:在编程界内部人为规定一个,私有的用"_"开头
- 第二种方法:Symbol数据类型(但是Reflect.ownKeys可以查看)
const bar = Symbol('bar');
class Point {
// 私有方法
[bar](){
console.log('x')
}
}
let point = new Point()
console.log(Reflect.ownKeys(Point.prototype));
//[ 'constructor', Symbol(bar) ]
类的取值函数(getter)和存值函数(setter)
class MyClass {
get name() {
return 'getter';
}
set name(value) {
console.log('setter: '+value);
}
}
var descriptor = Object.getOwnPropertyDescriptor(
CustomHTMLElement.prototype, "name"
);
- 类的get和set和以前的构造函数的是一样的
- 存值函数和取值函数是设置在属性的 Descriptor 对象上的
new.target
new是从构造函数生成实例对象的命令。ES6 为new命令引入了一个new.target属性,该属性一般用在构造函数之中,返回new命令作用于的那个构造函数。如果构造函数不是通过new命令或Reflect.construct()调用的,new.target会返回undefined,因此这个属性可以用来确定构造函数是怎么调用的。
class Point {
constructor() {
console.log(new.target === Point); //true
}
}
let point = new Point();
只能在构造函数constructor中使用new.target。其他地方使用会报错
function Point2(name) {
if (new.target === Point2) {
this.name = name;
} else {
throw new Error('必须使用 new 命令生成实例');
}
}
let point3 = new Point2('sha');
let point2 = Point2.call({}, 'li'); //抛出异常
类注意点
- 类的内部默认就是严格模式
use strict
- 类不存在声明提前,有临时性死区
- this指向会随着调用者改变的