1. 类的由来
JavaScript 语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子。
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.fn = function () {
return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。
基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
上面的代码用 ES6 的class改写,就是下面这样。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
fn() {
return '(' + this.x + ', ' + this.y + ')';
}
}
let p = new Point(1, 2); // 直接对类使用new命令, 生成实例对象, 跟构造函数使用方式一样
typeof Point; // Function
console.log(Point === Point.prototype.constructor); // true
// ES6 的类,完全可以看作构造函数的另一种写法
上面代码定义了一个“类”,可以看到里面有一个constructor()方法,这就是构造方法,而this关键字则代表实例对象。这种新的 Class 写法,本质上与本章开头的 ES5 的构造函数Point是一致的。
Point类除了构造方法,还定义了一个 fn()方法。注意,定义方法时前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法与方法之间不需要逗号分隔,加了会报错。
2. 创建类
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
constructor()方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor()方法,如果没有显式定义,一个空的constructor()方法会被默认添加。
类其实就是
构造函数+原型
的一种简化语法。都是为了批量创建某一类对象。
class Animal{
// 该方法在使用new命令生成实例对象时,会被调用
// 其中的 this 就指向实例对象
constructor(name,age) {
this.name=name;
this.age=age;
}
eat(){
console.log("eating.....")
}
drinks(){
console.log("drinking....")
}
play(){
console.log("play....")
}
//静态方法
static happy(){
console.log("happy.....")
}
}
let a1 = new Animal('dog',6);
let a2 = new Animal('cat',3);
// 1. 类相当于实例的原型,所有在类中定义的方法,都会被实例继承
console.log(Animal.prototype); // 具备 construcotr eat drinks play 这些方法,但不具备 happy方法
// 2.如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”
Animal.happy(); // happy.....
// 3. name, age 属性被添加到了每一个实例上, 是实例自己的属性
console.log(a1.name, a1.age);
console.log(a2.name, a2.age);
// 4. a1, a2 都具备类的方法, 这些类中定义的方法都被放在了实例的原型上 a1.__proto__ == Animal.prototype
a1.eat();
a2.eat();
3. 类的继承
所谓继承就是让 子类 具备 父类 的属性和方法。可以通过extends关键字实现继承。
在ES6实现继承中会有constructor构造函数,而实现继承的子类构造函数中必须先调用super()方法,此处的super()为父类的构造方法,而如果不调用,浏览器则会报错。
//比如我们定义一个Bird来继承刚才定义的Animal class Bird extends Animal{ constructor(name,age,color,cicle) { // 1. 执行super() 这一步实现了 子类实例对父类属性和方法的继承 super(); // 2. 加工子类实例 this.name = name; this.age = age; this.color=color; this.cicle = cicle; } play(){ console.log('飞到天上玩.....') } } var b1 = new Bird('黄鹂鸟',1,'yellow','是个球') console.log(b1); b1.eat(); b1.play();
3.1 super
ES6 规定,子类必须在constructor()方法中调用super(),否则就会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。如果不调用super()方法,子类就得不到自己的this对象。
4. 类的注意事项及特点
-
类里面的constructor函数, 可以看做
构造函数
-
类里面的所有方法都是定义在
原型
上面 -
new生成实例时, 就会自动调用constructor函数
-
类里面的函数 不能加function
-
类里面的多个函数之间不需要加