JavaScript传统的定义构造函数的定义方式是以下:javascript
function Point(x,y){ this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; let p = new Point(1,2); console.log(p)
运行结果:java
ES6里面经过类这样表示:编程
class Point{ constructor(x,y){ this.x = x; this.y = y; } toString(){ return '('+this.x+','+this.y+')'; } } let p = new Point(1,2); console.log(p)
运行结果:函数
经过上面的代码能够看出ES6里面经过class关键字定义的类实际上是语法糖而已,其中绝大多数功能ES5里面已经实现过了,只不过ES6里面的class让对象原型的写法更加清晰,更像面向对象编程的写法而已。
上面定义的“类”里面,能够看出来有一个constructor方法,这就是构造方法。里面还有this关键字表明了实例对象。也就是说ES5里面的构造函数,就是ES6里面的类里面的构造方法。
Point类里面还有一个方法叫toString,注意“类”里面定义方法的时候不用加function关键字,直接把方法定义写进去就好了。还有一点就是方法之间不用加逗号了,若是加了会报错的。this
class Point { // ... } typeof Point // "function" Point === Point.prototype.constructor // true
类的数据类型是函数,类自己指的就是构造函数spa
function Point(){ // ... } console.log(Point === Point.prototype.constructor);//true
ES6里面的类,彻底能够说是构造函数的另外一种写法。prototype
class Bar { doStuff() { console.log('stuff'); } } var b = new Bar(); b.doStuff() // "stuff"
使用的时候,也是直接对类使用new命令,跟构造函数的用法彻底一致。code
构造函数的prototype属性,ES6“类”里面依然存在的,类里面定义的全部的方法,其实都添加到类的prototype属性里面。对象
class Point { constructor() { // ... } toString() { // ... } toValue() { // ... } } // 等同于 Point.prototype = { constructor() {}, toString() {}, toValue() {}, };
在类的实例上面调用方法,其实就是调用原型上的方法。ip
class Point { constructor() { // ... } toString() { // ... } toValue() { // ... } } let p = new Point(); console.log(p.toString === Point.prototype.toString);//true
constructor方法是类的默认方法,经过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,若是没有显式定义,一个空的constructor方法会被默认添加。
class Point { } // 等同于 class Point { constructor() {} }
类经过new关键字实例化的时候默认自动调用constructor构造方法,constructor构造方法返回一个类实例(即this对象)
ES6类里面实例化对象,跟ES5构造函数的实例化相似的都是经过new关键字实例化出来的。惟一的区别是ES5构造函数也能普通函数调用的形式调用。可是ES6类必须经过new调用实例化对象出来,否则会报错的。
class Point { // ... } // 报错 var point = Point(2, 3); // 正确 var point = new Point(2, 3);
类里面显示定义的全部属性和箭头方法都会存放到this对象里面,可是类里面除了箭头方法以外的全部方法都存放到类prototype原型里面。
//定义类 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } say = ()=>{ } } 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 point.hasOwnProperty('say') //true
上面代码中,x和y都是实例对象point自身的属性(由于定义在this变量上),因此hasOwnProperty方法返回true,而toString是原型对象的属性(由于定义在Point类上),因此hasOwnProperty方法返回false。这些都与 ES5 的行为保持一致。
与 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'