JavaScriptWeb前端之路Web 前端开发

ES6之class

2016-08-02  本文已影响172人  光哥很霸气

解决的问题

更加清晰的书写继承,面向对象编程

基本语法

constructor

  1. 构造方法,this关键字代表构造对象
  2. new一个类时,自动执行该方法
  3. 必须有constructor,没有的话一个空的方法会被默认添加
  4. constructor默认返回该对象实例(this),也可以手动更改

函数

不用加function以及逗号,以下为es5和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);
//定义类
class Point {
  constructor(x, y) {
this.x = x;
this.y = y;
}
  toString() {
return '(' + this.x + ', ' + this.y + ')';
}}

使用

class Bar {
  do Stuff(){
    console.log('stuff');
  }
}
var b = new Bar();
b.doStuff() //  "stuff"

通过new
原理
可以把类,看作构造函数的另一种写法

class Pointer{
}
typeof Pointer //function
Pointer == Pointer.prototype.constructor //true

以上表示类的数据类型是函数,并且类本身指向其构造函数

类的实例对象

  1. 必须使用new操作符实例化对象
  2. 由于类的方法都是通过prototype实现的,因此可以像这样添加函数
var p1 = new Point(2,3);
var p2 = new Point(3,2);
p1.__proto__.printName = function () { 
return 'Oops';
};
p1.printName() // "Oops"
p2.printName() // "Oops"
var p3 = new Point(4,2);
p3.printName() // "Oops"

其他知识点

  1. 不存在变量提升
  2. 可以使用class表达式
  3. 类和模块的内部,默认都是严格模式
  4. 类的name属性总是返回class后面的类名

2.继承

  1. 由于子类没有自己的this对象,因此子类的contstuctor内必须调用super方法,否则报错
  2. 如果子类没有定义constructor,会自动添加
  3. Class同时拥有prototype__proto__属性
  4. 子类的__proto__属性,表示构造函数的继承,总是指向父类
  5. 子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。
  6. 只要是有prototype属性的函数都能被继承,除了Function.prototype
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 调用父类的constructor(x, y)
    this.color = color;
  }
  toString() {
  return this.color + ' ' + super.toString();
  // 调用父类的toString()
  }}

ES5的继承,实际是想创造子类的实例对象this,然后将父类的方法绑定子类的this(Parent.apply(this));ES6则不同,实质是先创造父类的实例对象(所以要先调用super()),然后子类的构造函数再修改this。

继承目标

3种特殊情况

第一种,子类继承Object

class A extend Object{
}
A.__proto__ = Object;
A.prototype.__proto__ = Object.prototype;

这种情况A相当于Object的复制,A的实例就是Object的实例。

第二种 不存在任何继承

Class A{}
A.__proto__ = Function.prototype;
A.prototype.__proto__ = Object.prototype;

A作为一个基本对象,那么直接继承自Function,但由于new一个A后返回的是一个空对象,因此A的对象继承自Object.prototype.

第三种 子类继承null

class A extend null{}
A.__proto__ = Function.prototype;
A.prototype.__proto = undefined;

因为new一个A后的实例,不继承任何方法,因此为undefined。

super

  1. super作为函数调用时,super指父类构造函数
  2. super作为对象调用时,super代表父类,可以调用父类实例的方法属性以及静态方法

子类的__proto__

  1. 子类实例的__proto__不等于父类实例的__proto__
  2. 子类实例__proto____proto__是父类实例的__proto__
  3. 也就是说子类原型的原型是父类的原型。
  4. 因此子类实例可以通过该方法修改父类实例方法。

继承原生构造函数

可以通过继承原生构造函数,如Array,从而获得Array所有属性和方法,并且可以扩充而不会影响Array的实例。

Class的get和set

class CustomHTMLElement {
  constructor(element) {
    this.element = element;
  }

  get html() {
    return this.element.innerHTML;
  }

  set html(value) {
    this.element.innerHTML = value;
  }
}

var descriptor = Object.getOwnPropertyDescriptor(
  CustomHTMLElement.prototype, "html");
"get" in descriptor  // true
"set" in descriptor  // true
  1. 当对html属性进行读取和设置值时,get和set修饰符会进行拦截。
  2. get和set函数是设置在属性的descriptor上的。

Class的静态方法

  1. 可以直接通过Class调用静态方法,并且不能通过实例调用
  2. 父类静态方法可以被子类继承,子类可以通过自身调用父类静态方法,或者通过super调用

Class的静态属性和实例属性

静态属性是指定义在class本事的属性,而不是对象this属性。

class Foo {
}

Foo.prop = 1;
Foo.prop // 1

因为ES6规定,class内部只有静态方法,没有静态属性,所以只能这么写。


以下为ES7提案,被babel支持。

实例属性

class MyClass {
  myProp = 42;

  constructor() {
    console.log(this.myProp); // 42
  }
}

不用定义在constructor里。

静态属性

class MyClass {
  static myStaticProp = 42;

  constructor() {
    console.log(MyClass.myProp); // 42
  }
}
上一篇下一篇

猜你喜欢

热点阅读