基本写法
es6 只是一个语法糖,底层还是原型链。例如:
// 构造函数写法
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);
// es6 类的写法
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
var p = new Point(1, 2);
这两种写法是等效的
一些说明
// 类的所有方法都定义在类的prototype属性上面,比如:
Point.prototype = {
constructor() {},
toString() {}
};
// 在类的实例上面调用方法,其实就是调用原型上的方法
class B {}
let b = new B();
b.constructor === B.prototype.constructor // true
constructor 方法
类的默认方法,通过new命令生成对象实例时,自动调用该方法。如果没有显式的定义则会自动添加
取值函数(getter)和存值函数(setter)
与 ES5 一样,在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
class MyClass {
constructor() {
// ...
}
get prop() {
return 'getter';
}
set prop(value) {
console.log('setter: '+value);
}
}
let inst = new MyClass();
inst.prop = 123;
// setter: 123
inst.prop
// 'getter'
类的属性名,可以采用表达式
let methodName = 'getArea';
class Square {
constructor(length) {
// ...
}
[methodName]() {
// ...
}
}
Class 表达式
const MyClass = class Me {
getClassName() {
return Me.name;
}
};
let inst = new MyClass();
inst.getClassName() // Me
如果在函数内部没用到则可以简写
const MyClass = class {
getClassName() {
return 1;
}
};
let inst = new MyClass();
inst.getClassName() // 1
采用 Class 表达式,可以写出立即执行的 Class。
let person = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}('张三');
person.sayName(); // "张三"
static关键字
表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
class Foo {
static classMethod() {
return 'hello';
}
}
Foo.classMethod() // 'hello'
var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
实例属性的新写法
实例属性既可以写在 constructor 里,也可以直接写在顶层
class IncreasingCounter {
constructor() {
this._count = 0;
}
}
class IncreasingCounter {
_count = 0;
}
静态属性static
静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性。
class MyClass {
static myStaticProp = 42;
constructor() {
console.log(MyClass.myStaticProp); // 42
}
}
私有方法和私有属性
之前解决方案:
1、命名用下划线_
class Widget {
// 公有方法
foo (baz) {
this._bar(baz);
}
// 私有方法
_bar(baz) {
return this.snaf = baz;
}
// ...
}
2、提案中
class IncreasingCounter {
// 私有属性
#count = 0;
get value() {
console.log('Getting the current value!');
return this.#count;
}
// 私有方法
#increment() {
this.#count++;
}
}
注:typescript 对 class 有一些优化,我们在 typescript 中可以使用 private
之所以要引入一个新的前缀#表示私有属性,而没有采用private关键字,是因为 JavaScript 是一门动态语言,没有类型声明,使用独立的符号似乎是唯一的比较方便可靠的方法,能够准确地区分一种属性是否为私有属性。