class的基本语法
class Point{ constructor(x, y){ this.x = x; this.y = y; } tostring(){ return '(' + this.x + ', ' + this.y + ')'; } }
在以上代码中,constructor就是构造方法,this关键字就代表实例对象。
类的数据类型实际上就是funtion,类本身就指向构造函数。
typeof Point === 'function' // true
Point === Point.prototype.constructor // true
创建实例对象时,也是使用new关键字。prototype原型对象,在class中也存在。class中的方法都是定义在prototype原型对象上的。
var p = new Point();
class内部定义的方法,都是不可枚举的
Object.keys(Point.prototype) // []
constructor方法
是类的默认方法,当通过new创建实例时,都会默认调用该方法。每一个类都必须有一个constructor方法,如果没有显示定义,则会给其默认定义一个空的constructor方法。
class Point{ } // 等同于 class Point{ constructor(){} }
constructor默认返回实例对象,即this,也可以指定返回另一个对象
class Point{ constructor(){ return Object.create(null) } }
new Point() instanceof Point // false
类的实例
必须通过new关键字来创建类的实例,否则会报错。
和ES5一样,除非是显示定义在实例本身上的属性(即定义在this上的),其他的属性都是定义在实例的原型对象上(即定义在class上的)
class Point{
constructor(x, y){
this.x = x;
this.y = y;
}
tostring(){
return '(' + this.x + ', ' + this.y + ')';
}
}
var p = new Point(2, 3);
p.hasOwnProperty('x')// true p.hasOwnProperty('y')// true p.hasOwnProperty('tostring')// false p.__proto__.hasOwnProperty('tostring')// true
与ES5一样,class的所有实例共享一个原型对象__proto__。通过一个实例更改了__proto__上面的属性或方法,通过其他实例获取__proto__上的属性或方法时也是更改后的值。所以使用__proto__时要慎重
取值函数和存值函数
与ES5一样,class内部也可以设置get和set方法来对设置属性和获取属性的操作进行拦截。存值函数和取值函数是设置在属性的 Descriptor 对象上的
属性表达式
类的属性名,可以采用表达式
let methodName = 'myMethod'; class Point{ constructor(x, y){ this.x = x; this.y = y; } [methodName](){} }
以上的Point类的方法名为myMethod
class表达式
class同样可以使用表达式定义
const myClass = class Me{ getclassname(){ return Me.name; } }
以上代码通过表达式定义了一个类,这个类的名称是Me,但是这个Me只能在类内部使用,在外部引用类只能使用myClass。如果类内部没有用到的话,可以省略Me。
可以通过这种方式创建立即执行类
let Person = new class{ constructor(name){ this.name = name; } getName(){ console.log(this.name) } }('ashen')
注意点
- 严格模式:类内部默认是采用严格模式的
- 不存在提升。
- name属性。就是紧跟在class关键字后面的类名
- 如果类中某个方法是generator方法,那么这个方法默认返回一个该class类的遍历器,for...of..循环会自动调用这个遍历器
- 类内的this默认指向实例对象。但是如果将类内的方法单独提出来使用,this就会指向undefined,从而找不到该方法而报错。
- 可以通过在构造函数中绑定this解决
- 也可以通过使用箭头函数实现
constructor() { this.getThis = () => this; }
静态方法
类中定义方法时,如果带有关键字static,那么此方法是类的静态方法。只能被类调用,不能被类的实例对象调用。静态方法中的this指向class本身。
父类的静态方法,可以被子类继承。子类也可以通过super对象调用父类的静态方法
class father{ static getTime(){ return '12 点' } } class son extends father{ static getTime(){ return super.getTime() + ',too'; } }
son.getTime() // 12 点,too
实例属性的新写法
之前都把实例属性写在constructor函数中的this上,其实还可以定义在函数的顶层
class IncreasingCounter { _count = 0; get value() { console.log('Getting the current value!'); return this._count; } increment() { this._count++; } }
在以上代码中,_count就是实例属性。其依然不存在于class的原型对象上
静态属性
在类外为类添加静态属性,这个属性是类的属性,不是实例的属性。
class Point{
}
Point.prop = 1; // 为Point类添加了一个静态属性prop
new.target属性
该属性一般在构造函数中使用,返回new命令作用于的那个构造函数。也可以用于判断实例是否是通过new命令创建的。
class内部使用new.target,返回的是class
当子类继承父类时,new.target会返回子类