es6之class封装

传统的面向对象语言(比如 C++ 和 Java)是通过class类来生成实例对象,javascript则是通过构造函数+prototype来封装,所以,js在es6引入了class类的概念

用class定义一个类

//定义类
class Point {
  constructor(x, y) {
  // this关键字则代表实例对象
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
关于constructor
  • constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。

  • 执行这个constructor方法默认返回实例对象(即this)

使用时

var point = new Point();

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

1、关于class的prototype属性

类的所有方法都定义在类的prototype属性上面。

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

  toString() {
    // ...
  }
}

// 等同于

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

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

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

point是Point类的实例,它的constructor方法就是Point类原型的constructor方法。

Point.prototype.constructor指向的是Point这个类 而point.constructor的原型对象也是Point

此外,toString方法是Point类内部定义的方法,它是不可枚举的。这一点与 ES5 的行为不一致。

Object.keys(Point.prototype)
// 采用es6的class写法是 [], 用es5的 Point.prototype.toString = function() {
  // 即返回["toString"]
};
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
2、类的实例对象

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

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 的行为保持一致。

类的所有实例共享一个原型对象。

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

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

p1和p2都是Point的实例,它们的原型都是Point.prototype,所以proto属性是相等的。

3、类的私有方法和私有属性

ES6 不提供私有属性和私有方法,我们只能通过变通方法模拟实现。

一种是在命名上加以区别。私有方法用_foo(),即在方法前面添加下划线,表示这是一个只限于内部使用的私有方法。但是,这种命名是不保险的,在类的外部,还是可以调用到这个方法。

一种是利用Symbol值的唯一性,将私有方法的名字命名为一个Symbol值。

还有一种是索性将私有方法移出模块,因为模块内部的所有方法都是对外可见的。

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

  // ...
}

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

上面代码中,foo是公有方法,内部调用了bar.call(this, baz)。这使得bar实际上成为了当前模块的私有方法。

4、Class 的静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

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

Foo.classMethod() // 'hello'

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

Foo类的classMethod方法前有static关键字,表明该方法是一个静态方法,可以直接在Foo类上调用(Foo.classMethod()),而不是在Foo类的实例上调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。

注意 如果静态方法包含this关键字,这个this指的是类,而不是实例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值