概述
经典的老书害人啊,全是讨论怎么解决javascript里面用函数形式定义类的坑。结果es2015直接用class关键字解决了所有问题。虽然class关键字没有什么新东西,只是js现有继承结构的语法糖,但是用起来真的很方便。我把它们记录下来,供以后开发时参考,相信对其他人也有用。
参考:MDN Classes,MDN class declaration,MDN class expression,MDN function declaration,MDN function expression
定义一个类
有以下四种方式定义一个类:
- es2015规定的,类声明,只能定义一次,不然会报错,没有hoisting,推荐使用。
- es2015规定的,类表达式,可以定义多次,后面覆盖前面的,没有hoisting,不推荐使用。
- 函数声明,有hoisting,不推荐使用。
- 函数表达式,没有hoisting,不推荐使用。
//类声明,推荐
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
//类表达式,不推荐
var Rectangle = class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
//函数声明,不推荐
function Rectangle() {
this.height = height;
this.width = width;
}
//函数表达式,不推荐
var Rectangle = function() {
this.height = height;
this.width = width;
}
类中的属性和方法
类中有静态和实例的属性和方法。相关的定义如下所示:
//es2015中类的定义方式,推荐
class Animal {
//constructor是静态方法,在里面定义实例属性(我们不需要静态属性)
constructor(x, y) {
this.x = x;
this.y = y;
}
//实例方法
speak() {
return this;
}
//静态方法
static eat() {
return this;
}
}
//函数形式,不推荐
function Animal(x, y) {
this.x = x;
this.y = y;
};
Animal.prototype.speak = function() {
return this;
}
Animal.eat = function() {
return this;
}
需要注意的是,es2015中类的定义方式中的this会指向undefined;而函数方式中的this会指向全局对象。
//es2015中类的定义方式
let obj = new Animal();
obj.speak(); // Animal {}
let speak = obj.speak;
speak(); // undefined
Animal.eat() // class Animal
let eat = Animal.eat;
eat(); // undefined
//函数方式
let obj = new Animal();
let speak = obj.speak;
speak(); // global object
let eat = Animal.eat;
eat(); // global object
静态和实例的区别
静态类型和实例类型的区别如下:
- 静态类型:类可以直接调用的类型(不能被实例直接调用),在内存中只占一块区域,创建实例时不额外分配内存。
- 实例类型:实例调用的类型,每创建一个实例,都会在实例中分配一块内存。