class类

class类

constructor方法

constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。

如果定义了一个空的类Point,Javascript引擎会自动为它添加一个空的contructor方法。

contructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象。

1
2
3
4
5
6
7
class Foo {
constructor () {
return Object.create(null)
}
}

new Foo() instanceof Foo // false

上面代码中,constructor函数返回一个全新的对象,结果导致实例对象不是Foo类的实例。

类必须用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。

1
2
3
4
5
6
7
8
class Foo {
constructor () {
return Object.create(null)
}
}

Foo()
// Uncaught TypeError: Class constructor Foo cannot be invoked without 'new'

类的实例

实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 定义类
class Point{
constructor (x, y) {
this.x = x
this.y = y
}
toString () {
return 'x: ' + this.x + '; y: ' + this.y
}
}

var point = new Point(1, 2)

point.toString() // x: 1; y: 2

point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true

类所有的实例共享一个原型对象。

1
2
3
4
var p1 = new Point()
var p2 = new Point()

p1._proto_ === p2._proto_ === Point.protype

可以通过实例的__proto__属性为“类”添加方法,不推荐!!!使用实例的__proto__属性改写原型,必须相当谨慎,不推荐使用,因为这会改变“类”的原始定义,影响到所有实例。

取值函数(getter)和存值函数(setter)

在“类”的内部可以使用getset关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。

1
2


属性表达式

类的属性名,可以采用表达式

1
2
3
4
5
6
7
8
9
10
let methodName = 'getArea'

class Square {
contructor() {
// ...
}
[methodName] () {
// ...
}
}

上面代码中,Square类的方法名getArea,是从表达式得到的。

Class表达式

类支持使用表达式的形式定义

1
2
3
4
5
const MyClass = class Me {
getClassName () {
return Me.name // 相当于MyClass.name
}
}

这个类的名字是MyClass而不是MeMe只在 Class 的内部代码可用,指代当前类。如果内容没有使用到Me可以直接省略。

1
const MyClass = class { /* ... */ };

采用 Class 表达式,可以写出立即执行的 Class。

1
2
3
4
5
6
7
8
9
let person = new class {
constructor(name) {
this.name = name
}
sayName() {
console.log(this.name)
}
}('张三')
person.sayName() // "张三"

注意点

  1. 类和模块的内部默认就是严格模式。

  2. 不存在变量提升(hoist),必须保证子类在父类之后定义

  3. name属性,name属性总是返回紧跟在class关键字后面的类名

  4. Generator方法,如果某个方法前面加上(*)号就表示该方法是一个Generator函数。??????

  5. this指向,类的方法内部如果有this,默认指向类的实例。一旦单独使用该方法,很可能报错。(????)

    解决方法

    • 在构造方法中绑定this,这样就没问题了
    • 使用箭头函数
    • 使用Proxy,获取方法适合,自动绑定this

静态方法