类的简介
1.1 类的由来
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)
运行结果:
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关键字,直接把方法定义写进去就行了。还有一点就是方法之间不用加逗号了,如果加了会报错的。
class Point {
// ...
}
typeof Point // "function"
Point === Point.prototype.constructor // true
类的数据类型是函数,类本身指的就是构造函数
function Point(){
// ...
}
console.log(Point === Point.prototype.constructor);//true
ES6里面的类,完全可以说是构造函数的另一种写法。
class Bar {
doStuff() {
console.log('stuff');
}
}
var b = new Bar();
b.doStuff() // "stuff"
使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。
构造函数的prototype属性,ES6“类”里面依然存在的,类里面定义的所有的方法,其实都添加到类的prototype属性里面。
class Point {
constructor() {
// ...
}
toString() {
// ...
}
toValue() {
// ...
}
}
// 等同于
Point.prototype = {
constructor() {},
toString() {},
toValue() {},
};
在类的实例上面调用方法,其实就是调用原型上的方法。
class Point {
constructor() {
// ...
}
toString() {
// ...
}
toValue() {
// ...
}
}
let p = new Point();
console.log(p.toString === Point.prototype.toString);//true
1.2 constructor
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
class Point {
}
// 等同于
class Point {
constructor() {}
}
类通过new关键字实例化的时候默认自动调用constructor构造方法,constructor构造方法返回一个类实例(即this对象)
1.3 类的实例
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 的行为保持一致。
1.4 取值函数(getter)和存值函数(setter)
与 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'
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。