let amy = new Person("Amy"); amy.sayHello(); // Hello Amy
需要注意的是 class 只是一种语法糖,即一个 class 其实本质上就是一个函数
classPerson{ // ... }
console.log(typeof Person); // function
类与构造函数有如下不同:
类的声明不会提升到作用域的顶部
在类内部的代码自动运行在严格模式 (strict mode) 之下
类中的方法都是不可枚举的
类中的方法都没有内置的 [[Construct]] 方法,所以当你 new 一个类内部的方法时,会抛出错误
不使用 new 调用类会发生错误
在类中的方法中不能修改类名
classPerson{ contructor() { // 不能在方法中修改类名 Person = "foo"; } }
所以上面类的声明与下面的代码等价
// 1. 类的声明不会提升到作用域的顶部 let Person = (function (o, properties) { // 2. 在类内部的代码自动运行在严格模式 (strict mode) 之下 "use strict";
// 6. 在类中的方法中不能修改类名 (使用 const 定义) const Person = function (name) { // 5. 不使用 new 调用类会发生错误 if (typeofnew.target === 'undefined') { thrownewError("Must be called by new"); } this.name = name; };
Object.defineProperty(Person.prototype, "sayHello", { value: function () { // 4. 类中的方法都没有内置的 [[Construct]] 方法,所以当你 new 一个类内部的方法时,会抛出错误 if (typeofnew.target !== 'undefined') { thrownewError("Method in class can't be called by new!"); } console.log(`Hello ${this.name}`); }, // 3. 类中的方法都是不可枚举的 enumerable: false, writable: false, configurable: false });
return Person; })();
类表达式
类表达式的概念与函数表达式相对应
let Person = class{ constructor(name) { this.name = name; } sayHello() { console.log(`Hello ${this.name}`) } };
或者
let Person = classPerson2{ // ... };
console.log(typeof Person); // function console.log(typeof Person2); // undefined
上面我们在 Person 上定义了一个 print 方法,因为 Person 的实例继承的是 Person.prototype,所以 Person 的实例访问不了 print 方法,这种只可以通过类名访问的方法我们称为静态方法,在 class 定义的类中,通过在方法名前加 static 关键字表示该方法是静态方法
let stu = new Student("Alice"); stu.sayHello(); // Hello World console.log(stu instanceof Student); // true console.log(stu instanceof Person); // true
let stu = new Student("Alice"); stu.sayHello(); // Hello World console.log(stu instanceof Student); // true console.log(stu instanceof Person); // true
继承自其它类的类称为子类,或者派生类。在子类的构造方法 constructor 中,必须首先通过调用 super 方法来调用父类的构造函数,它会在这里初始化 this,如果没有调用 super 方法的话,会抛出错误,并且 super 方法只能被调用一次,且必须在访问 this 变量之前。