挖坑ECMAScript6-class

说明

ES6引入了 Class(类)这个概念,作为对象的模板,通过class关键字,可以定义类。

示例

//定义类
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

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

使用:

let a = new Point(1,2);
a.toString();

设定

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

let methodName = 'getArea';

class Square {
  constructor(length) {
    // ...
  }

  [methodName]() {
    // ...
  }
}

2.类和模块的内部,默认就是严格模式

3.constructor方法

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

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

class Foo {
  constructor() {
    return Object.create(null);
  }
}

4.类必须使用new调用,否则会报错

类跟普通构造函数不同,普通构造函数不用new也可以执行。

5.class表达式

与函数一样,类也可以使用表达式的形式定义。

const MyClass = class Me {
  getClassName() {
    return Me.name;
  }
};

上面代码使用表达式定义了一个类。需要注意的是,这个类的名字是MyClass而不是Me,Me只在 Class 的内部代码可用,指代当前类。

如果类的内部没用到的话,可以省略Me,也就是可以写成下面的形式。

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

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

let person = new class {
  constructor(name) {
    this.name = name;
  }

  sayName() {
    console.log(this.name);
  }
}('张三');

person.sayName(); // "张三"

6.类不存在变量提升

必须先定义类,才能使用类

7.类的方法内部如果含有this,它默认指向类的实例

8.“类名.name”可以获取class关键字后面的类名

9.在类的内部可以使用get和set关键字

使用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'

10.类可以用static设置静态方法。父类的静态方法,可以被子类继承

11.ES6规定,Class 内部只有静态方法,没有静态属性(虽然通过某种方式可以实现同样的功能)

继承

Class 可以通过extends关键字实现继承。

class Point {
}

class ColorPoint extends Point {
}

通过extends关键字,可以继承父类的所有属性和方法。

extends的限制

  1. 子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。ES6 的继承机制实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this
  2. 如果子类没有定义constructor方法,这个方法会被默认添加
  3. 在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错
  4. 父类的静态方法,也会被子类继承
  5. Object.getPrototypeOf方法可以用来从子类上获取父类

关于super

super这个关键字,既可以当作函数使用,也可以当作对象使用。

1.当super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数。

class A {}

class B extends A {
  constructor() {
    super();
  }
}

注意,super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B。

class A {
  constructor() {
    console.log(new.target.name);
  }
}
class B extends A {
  constructor() {
    super();
  }
}
new A() // A
new B() // B

上面代码中,new.target指向当前正在执行的函数。可以看到,在super()执行时,它指向的是子类B的构造函数,而不是父类A的构造函数。也就是说,super()内部的this指向的是B。
作为函数时,super()只能用在子类的构造函数之中,用在其他地方就会报错。

2.当super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
在普通方法中,由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。

class A {
  constructor() {
    this.p = 2;
  }
}

class B extends A {
  get m() {
    return super.p;
  }
}

let b = new B();
b.m // undefined

但是如果属性定义在父类的原型对象上,super就可以取到。

class A {}
A.prototype.x = 2;

class B extends A {
  constructor() {
    super();
    console.log(super.x) // 2
  }
}

let b = new B();

另外,ES6 规定,在子类普通方法中通过super调用父类的方法时,方法内部的this指向当前的子类实例。

class A {
  constructor() {
    this.x = 1;
  }
  print() {
    console.log(this.x);
  }
}

class B extends A {
  constructor() {
    super();
    this.x = 2;
  }
  m() {
    super.print();
  }
}

let b = new B();
b.m() // 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值