定义类
类实质是个”特殊的函数”,就像你能够定义的函数表达式和函数声明一样, 类语法有两个组成部分: 类表达式和类声明。
class的本质是function。它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程语言的语法。
1 | class Ponit { // 类声明 按照书写习惯 类名要大写 就像构造函数一样。 |
上面的代码表明,类的数据类型就是函数,类本身就指向构造函数。 使用的时候也是直接对类使用new命令,和构造函数的用法一样。
构造函数的prototype属性在ES6的”类”上继续存在。事实上,类的所有方法都定义在prototype属性上。
1 | class B { |
由于类的方法(除constructor以外)都定义在prototype对象上,所以类的新方法可以添加在prototype对象上。 另外,类的内部定义的所有方法都是不可枚举的。
提升
函数声明和类声明宅男有一个重要区别是函数声明会提升,类声明不会。你首先需要声明你的类,然后访问它,否则代码会抛出一个ReferenceError。 所以在继承中也必须保证之类在父类后定义
constructor方法
constructor方法是类的默认方法,通过new命令生成对象实例时自动调用该方法。一个类必须有constructor方法,如果显示定义,JavaScript引擎会自动为它添加一个空的constructor方法。
constructor方法默认返回实例对象(即this),不过完全可以定返回另外一个对象。
1 | class Foo { |
一个类只能拥有一个名为 “constructor”的特殊方法。如果类包含多个constructor
的方法,则将抛出 一个SyntaxError
。
一个构造函数可以使用 super
关键字来调用一个父类的构造函数。
类的实例对象
生成实例对象的写法和ES5完全一样,也是使用new命令。如果忘记加上new, 像函数那样调用Class将会报错。
1 | class Point { |
1 | class P { |
上面代码中,x和y都是实例对象p自身的属性(因为定义在this变量上),所以hasOwnProperty方法返回true。而toString是原型对象的属性(因为定义在P类上),所以hasOwnProperty方法返回false。
与ES5一样,类的所有实例共享一个原型对象。
1 | let p1 = new P(2, 3) |
上面的代码中,p1和p2都是P的实例,它们的原型都是P.prototype,所以 __proto__
属性是相等的。这也意味着,可以通过实例的 __proto__
属性为类添加方法。
静态方法
类相对于实例的原型,所有在类中定义的方法都会被实例继承。如果在一个方法前加上static关键字,就表示该方法不会被实例继承,而是直接通过类调用,成为”静态方法”。
static
关键字用来定义一个类的一个静态方法。调用静态方法不需要实例化该类,但不能通过一个类实例调用静态方法。静态方法通常用于为一个应用程序创建工具函数。
1 | class Point { |
静态属性
1 | class Foo { |
上面的写法可读/写Foo类的静态属性prop。 目前,只有这种学法可行,因为ES6明确规定,Class内部只有静态方法,没有静态属性。