共计 3544 个字符,预计需要花费 9 分钟才能阅读完成。
概述
class (类)作为对象的模板被引入,可以通过 class 关键字定义类。类简要说明
类的本质是 function, 是基本原型继承的语法糖。所以,JS 中继承的模型是不会被改变的。
类既然是函数,那与函数有何不同呢?我们为什么要使用类呢?
有时间,先看一下 MDN od
- 函数声明可以被提升,而类声明与 let/const 声明类似,不能被提升,也就是在真正执行声明之前,它们会一直存在于临时死区中。
- 类声明中的所有代码将自动运行在严格模式下,而且无法强行让代码脱离严格模式。
- 类中的所有方法,都是不可枚举的。而普通自定义类型中,必须通过 Object.defineProperty()方法来指定某方法不可枚举。
- 每个类都有一个 [[Construct]] 的内部方法,通过关键字 new 调用那些不含 [[Construct]] 的方法会导致程序抛出错误。
- 使用除关键字 new 之外的方式调用构造函数会导致程序抛出错误。
- 在类中修改类名会导致程序报错。
类声明
首先 class 关键字,然后是类的名字,其它部分的语法,类似于对象字面量方法的简写形式,但不需要在各元素之间使用逗号分隔。
class HelloClass {constructor(greeting) {this.greeting = greeting;} | |
sayGreeting(){console.log(this.greeting); | |
} | |
} | |
let hello = new HelloClass('Hello'); | |
hello.sayGreeting(); // Hello | |
console.log(hello instanceof HelloClass); // true | |
console.log(hello instanceof Object); // true | |
console.log(typeof HelloClass); // function | |
console.log(typeof HelloClass.prototype.sayGreeting); // function |
分析:
- constructor 为保留方法名,是用来构建对象的,不可用作其它用途。
- 函数定义之前,不需要添加 function 关键字。
- 类的属性不可被赋予新值,HelloClass.prototype 是一个只可读类属性。
与之等价的 ES5 声明
let HelloClass = (function(){ | |
"use strict"; | |
const HelloClass = function(greeting) {if (typeof new.target === 'undefined') {throw new Error("必须通过关键字 new 调用构造函数"); | |
} | |
this.greeting = greeting; | |
Object.defineProperty(HelloClass.prototype, "sayGreeting", {value: function() {if (typeof new.target !== 'undefined') {throw new Error("不可使用关键字 new 调用构造函数"); | |
} | |
console.log(this.greeting); | |
}, | |
enumerable: false, | |
writable: true, | |
configurable: true | |
}); | |
} | |
return HelloClass; | |
}()); | |
let hello = new HelloClass('Hello'); | |
hello.sayGreeting(); | |
console.log(hello instanceof HelloClass); | |
console.log(hello instanceof Object); | |
console.log(typeof HelloClass); | |
console.log(typeof HelloClass.prototype.sayGreeting); |
类表达式
类表达式可以是被命名的或匿名的。赋予一个命名类表达式的名称是类的主体的本地名称。和 function 的表达式类似, 但不会像函数声名或和函数表达式一样被提升。
/* 匿名类 */ | |
let Rectangle = class {constructor(height, width) { | |
this.height = height; | |
this.width = width; | |
} | |
}; | |
console.log(typeof Rectangle); // function |
/* 命名的类 */ | |
let Rectangle = class Rectangle1 {constructor(height, width) { | |
this.height = height; | |
this.width = width; | |
} | |
}; | |
console.log(typeof Rectange); // function | |
console.log(typeof Rectange1); // undefined |
在 JS 中,函数为一等“公民”,可以传入函数,也可以从函数中返回,还可以赋值给变量的值。类 也是 JS 中的一等公民。
访问器
- getter | |
- setter |
class Rectangle { | |
// constructor | |
constructor(height, width) { | |
this.height = height; | |
this.width = width; | |
} | |
// Getter | |
get area() {return this.calcArea() | |
} | |
// Method | |
calcArea() {return this.height * this.width;} | |
} | |
const square = new Rectangle(10, 10); | |
console.log(square.area); | |
// 100 |
可计算成员
const methodName = "sayGreeting"; | |
class HelloClass {constructor(greeting) {this.greeting = greeting;} | |
[methodName]() {console.log(this.greeting); | |
} | |
} | |
let hello = new HelloClass('Hello'); | |
hello.sayGreeting(); // Hello | |
hello[methodName](); // Hello |
可计算访问器属性。
const propertyName = "greeting"; | |
class HelloClass {constructor() { } | |
get [propertyName]() {return this.greetingStr;} | |
set [propertyName](value) {this.greetingStr = value;} | |
} | |
let hello = new HelloClass(); | |
hello.greeting = 'Hello'; | |
console.log(hello.greeting); |
生成器方法
class NormClass {*createIterator() { | |
yield 1; | |
yield 2; | |
yield 3; | |
} | |
} | |
let instance = new NormClass(); | |
let iterator = instance.createIterator(); | |
console.log(iterator.next()); // {value: 1, done: false} | |
console.log(iterator.next()); // {value: 2, done: false} | |
console.log(iterator.next()); // {value: 3, done: false} | |
console.log(iterator.next()); // {value: undefined, done: true} |
为类定义默认迭代器。
class Collection {constructor() {this.items = []; | |
} | |
*[Symbol.iterator]() {yield *this.items.values(); | |
} | |
} | |
var coll = new Collection(); | |
coll.items.push(1); | |
coll.items.push(2); | |
coll.items.push(3); | |
for (let i of coll) {console.log(i); | |
} | |
// 1 | |
// 2 | |
// 3 |
静态成员
class Animal {speak() {return this;} | |
static eat() {return this;} | |
} | |
let obj = new Animal(); | |
console.log(obj.speak()); // Animal {} | |
let speak = obj.speak; | |
console.log(speak()); // undefined | |
console.log(Animal.eat()); // class Animal | |
let eat = Animal.eat; | |
console.log(eat()); // undefined |
正文完
发表至: javascript
2019-07-20