文章

Class的基本语法

Class的基本语法

Class的基本语法

Class的基本语法

简介

JavaScript 语言中,生成实例对象的传统方法是通过构造函数:

1
2
3
4
5
6
7
8
9
10
function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};

var p = new Point(1, 2);

等同于:

1
2
3
4
5
6
7
8
9
10
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

可以看到里面有一个 constructor() 方法,这就是构造方法,而 this 关键字则代表实例对象。

1
2
3
4
5
6
class Point {
  // ...
}

typeof Point // "function"
Point === Point.prototype.constructor // true

上面代码表明,类的数据类型就是函数,类本身就指向构造函数。


使用new 命令

1
2
3
4
5
6
7
8
class Bar {
  doStuff() {
    console.log('stuff');
  }
}

const b = new Bar();
b.doStuff() // "stuff"

构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Point {
  constructor() {
    // ...
  }

  toString() {
    // ...
  }

  toValue() {
    // ...
  }
}

// 等同于

Point.prototype = {
  constructor() {},
  toString() {},
  toValue() {},
};

因此,在类的实例上面调用方法,其实就是调用原型上的方法

1
2
3
4
class B {}
const b = new B();

b.constructor === B.prototype.constructor // true

prototype对象的constructor()****属性,直接指向“类”的本身,这与 ES5 的行为是一致的。

1
Point.prototype.constructor === Point // true

类的内部所有定义的方法,都是不可枚举的(non-enumerable)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Point {
  constructor(x, y) {
    // ...
  }

  toString() {
    // ...
  }
}

Object.keys(Point.prototype)
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]

上面代码中 toString()方法是Point类内部定义的方法,它是不可枚举的

1
2
3
4
5
6
7
8
9
10
11
12
var Point = function (x, y) {
  // ...
};

Point.prototype.toString = function () {
  // ...
};

Object.keys(Point.prototype)
// ["toString"]
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]

上面 ES5 的写法,toString()方法就是可枚举的。

constructor 方法

constructor()方法是类的默认方法,通过new****命令生成对象实例时,自动调用该方法。

一个类必须有constructor()方法,如果没有显式定义,一个空的constructor()方法会被默认添加。

1
2
3
4
5
6
7
class Point {
}

// 等同于
class Point {
  constructor() {}
}

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

类的实例

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//定义类
class Point {

  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }

}

var point = new Point(2, 3);

point.toString() // (2, 3)

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

上面代码中,x和y都是实例对象point自身的属性(因为定义在this对象上),所以hasOwnProperty()方法返回true,而toString()是原型对象的属性(因为定义在Point类上),所以hasOwnProperty()方法返回false。这些都与 ES5 的行为保持一致。

Object 的 hasOwnProperty() 方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。

与 ES5 一样,类的所有实例共享一个原型对象。

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

p1.__proto__ === p2.__proto__		//true

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

本文由作者按照 CC BY 4.0 进行授权

© 独行的风. 保留部分权利。

本站采用 Jekyll 主题 Chirpy

本站总访问量 本站访客数 本文阅读量