首页 > 其他 > 详细

ES6 (11):Class

时间:2019-06-05 18:55:40      阅读:86      评论:0      收藏:0      [点我收藏+]

ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。(所以其实不要和面向对象的class 混为一谈,因为并不是真正意义上的类)

 

ES5:(之前的博文中有记录过this,优先级new 是最高的,并且如果是new 方法创建的实例,等于是复制了一份,this指向自身)

技术分享图片

技术分享图片

 

 constructor构造方法,this关键字则代表实例对象(与ES5 一致)

class 创建的类与ES5 中创建的函数有所不同,下面如果直接执行call 方法,提示类的构造器不能没有new 去执行,必须要创建实例才可以。

技术分享图片

类的数据类型就是函数,类本身就指向构造函数

技术分享图片

 

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

技术分享图片

技术分享图片

class B {}
let b = new B();

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

 

 由于类的方法都定义在prototype对象上面,所以类的新方法可以添加在prototype对象上面。Object.assign方法可以很方便地一次向类添加多个方法。

class Point {
  constructor(){
    // ...
  }
}

Object.assign(Point.prototype, {
  toString(){},
  toValue(){}
});

 技术分享图片

设置对象原型的时候,a 丢到了Point 类的构造方法的原型中。

 

 

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

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

 内部所有定义的方法,都是不可枚举的(non-enumerable)。这一点与 ES5(可枚举) 的行为不一致。

 

 

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

//定义类
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

 

getter、setter:

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]() {
    // ...
  }
}

 技术分享图片

 

 表达式:(有点像函数)

const MyClass = class Me {
  getClassName() {
    return Me.name;
  }
};
const MyClass1 = class{
  getClassName() {
    return Me.name;
  }
};
const foo = function test(){}

 技术分享图片

 

采用 Class 表达式,可以写出立即执行的 Class(必须要有new)。

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

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

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

 

类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式。

类不存在变量提升(hoist),这一点与 ES5 完全不同。

技术分享图片

技术分享图片

 

变量提升到全局window。(作为使用new 创建的对象实例,本身this也是指向自身)

 

 由于本质上,ES6 的类只是 ES5 的构造函数的一层包装,所以函数的许多特性都被Class继承,包括name属性

 

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

class Foo {
  constructor(...args) {
    this.args = args;
  }
  * [Symbol.iterator]() {
    for (let arg of this.args) {
      yield arg;
    }
  }
}

for (let x of new Foo(‘hello‘, ‘world‘)) {
  console.log(x);
}
// hello
// world

 

 

类的方法内部如果含有this,它默认指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错。

 

全局方法/静态方法:如果静态方法包含this关键字,这个this指的是类,而不是实例

class Foo {
  static classMethod() {
    return ‘hello‘;
  }
}

Foo.classMethod() // ‘hello‘

var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function

 

class Foo {
  static bar() {
    this.baz();
  }
  static baz() {
    console.log(‘hello‘);
  }
  baz() {
    console.log(‘world‘);
  }
}

Foo.bar() // hello

 

类可以被继承(extend):Bar继承了Foo 类,Bar的原型指向Foo

技术分享图片

技术分享图片

静态方法也是可以从super对象上调用的(非静态方法也可以)。

class Foo {
  static classMethod() {
    return ‘hello‘;
  }
}

class Bar extends Foo {
  static classMethod() {
    return super.classMethod() + ‘, too‘;
  }
}

Bar.classMethod() // "hello, too"

 

实例属性除了定义在constructor()方法里面的this上面,也可以定义在类的最顶层(注意没有this)。

class IncreasingCounter {
  _count = 0;
  get value() {
    console.log(‘Getting the current value!‘);
    return this._count;
  }
  increment() {
    this._count++;
  }
}

 

 

静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性(第一种跟ES5 之前一样)。

class Foo {
}

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

 目前最新的写法。

class MyClass {
  static myStaticProp = 42;

  constructor() {
    console.log(MyClass.myStaticProp); // 42
  }
}

 

私有方法和私有属性(class 暂不直接支持,只有通过变通的方法,因为class 其内部this本身就是指向实例自身)

ES5:

技术分享图片

ES6:

class Widget {
  foo (baz) {
    bar.call(this, baz);
  }

  // ...
}

function bar(baz) {
  return this.snaf = baz;
}

 bar 成为了类的私有方法。

 

私有属性提案(chrom最新版可以使用了,火狐67.0 未支持)class加了私有属性。方法是在属性名之前,使用#表示,内部使用this.#xxx 访问。

技术分享图片

 

对比:

技术分享图片

 

 私有方法:貌似暂时不支持

 

 new是从构造函数生成实例对象的命令。ES6 为new命令引入了一个new.target属性,该属性一般用在构造函数之中,返回new命令作用于的那个构造函数。如果构造函数不是通过new命令或Reflect.construct()调用的new.target会返回undefined因此这个属性可以用来确定构造函数是怎么调用的

技术分享图片

 

 利用这个特点,可以写出不能独立使用、必须继承后才能使用的类(子类继承父类时,new.target会返回子类)

class Shape {
  constructor() {
    if (new.target === Shape) {
      throw new Error(‘本类不能实例化‘);
    }
  }
}

class Rectangle extends Shape {
  constructor(length, width) {
    super();
    // ...
  }
}

var x = new Shape();  // 报错
var y = new Rectangle(3, 4);  // 正确

 

ES6 (11):Class

原文:https://www.cnblogs.com/jony-it/p/10981103.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!