1.类声明:类声明不会提升,必须声明后访问,强制访问则抛出错误 referenceError
{
try {
let p = new Rectangle() // 报错 referenceError
} catch({message}) {
}
class Rectangle {
constructor(width, height) {
this.width = width
this.height = height
}
}
}
2.类表达式:
-
类表达式可以命名或不命名,命名类表达式的名称是该类体的局部名称, -
可以通过类的(而不是一个实例的)name属性来访问它
{
{
// 不命名
let Rectangle = class {
constructor(width, height) {
this.width = width
this.height = height
}
}
// console.log(Rectangle.name) // Rectangle
}
{
// 命名
let Rectangle = class Rectangle2 {
constructor(width, height) {
this.width = width
this.height = height
}
}
// console.log(Rectangle.name) // Rectangle2
}
}
- 严格模式
-
类声明和类表达式的主体都执行在严格模式下 -
比如:构造函数,静态方法,原型方法,getter和setter都在严格模式下执行 - 构造函数
-
1.constructor方法是一个特殊的方法,该方法用于创建和初始化一个由class创建的对象 -
2.一个类只能有一个constructor方法,如果类包含多个constructor方法,则抛出错误 syntaxError -
3.一个构造函数可以使用super关键字来调用一个父类的构造函数 - 用原型和静态方法绑定this
-
当调用静态或原型方法时没有指定this的值,那么方法内的this值将被置为undefined。即使你未 -
设置'user strict',因为class体内部的代码总是在严格模式下执行。
{
let Rectangle = class {
constructor(w, h) {
try {
a = 2 // a is not defined
} catch({message}) {
}
this.w = w
this.h = h
}
static private_awidth = 100
static private_height = 200
// 私有面积数据
static area() {
return this.private_awidth * this.private_height
}
// 对外提供查询
area() {
try {
a = 2 // a is not defined
} catch({message}) {
// console.log(message)
}
return this.w * this.h + 'm²'
}
get area() {
return this.w * this.h
}
get girth() {
return (this.w + this.h) / 2
}
}
let p = new Rectangle(10, 10)
// console.log(Rectangle.area())
// console.log(p)
// console.log(p.area) // 面积
// console.log(p.girth) // 周长
}
{
class Subject {
chinese () {
return this
}
static math() {
return this
}
}
let s = new Subject()
// console.log(s.chinese()) // Subject {}
let c = s.chinese
// console.log(c()) // undefined
// console.log(Subject.math()) // class Subject
let m = Subject.math
// console.log(m()) // undefined
}
- 如果上述代码通过传统的基于函数的语法来实现,那么依据初始的this值,在非严格
- 模式下方法调用会发生自动装箱。若初始值是undefined,this值会被设为全局对象。
{
function Person() {
}
Person.prototype.say = function() {
return this
}
Person.eat = function() {
return this
}
let p = new Person()
let p1 = p.say
let p2 = Person.eat
// console.log(p1()) // global object
// console.log(p2()) // global object
}
- 实例的属性必须定义在类的方法里
- 静态的或原型的数据属性必须定义在类定义的外面
{
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
}
Person.sex = '男'
Person.prototype.adress = '深圳市'
let p = new Person('张三')
// console.log(p)
}
- 公有字段声明
-
公有类字段 -
公有静态字段和公有实例字段都是可编辑、可枚举和可配置的属性。因此,不同于私有对应值 -
的是,它们参与原型的继承
{
{
class Rectangle {
width = 10
height = 20
}
let r = new Rectangle()
// console.log(r.width, r.height) // 10, 20
}
{
class Rectangle {
static width = 10
static height = 20
}
let r = new Rectangle()
// console.log(r) // 无法访问r.width和r.height
}
{
class Rectangle {
publicMethod() {
return 'hello world'
}
}
}
}
- 公有静态字段
{
{
class Rectangle {
static width = 10
static height = 20
static area // 没有设定初始化的字段将默认被初始化为undefined
}
// console.log(Rectangle.width, Rectangle.height, Rectangle.area) // 10 20 undefined
let r = new Rectangle()
// console.log(r)
}
{
class Rectangle {}
// Rectangle.width = 10
// Rectangle.height = 20
Object.defineProperty(Rectangle, 'width', {
value: 10
})
Object.defineProperty(Rectangle, 'height', {
value: 20
})
// console.log(Rectangle.width, Rectangle.height) // 10 20
let r = new Rectangle()
// console.log(r.width, r.height)
}
{
class Rectangle {
static width
}
// console.log(Object.hasOwn(Rectangle, 'width')) // true
// console.log(Object.hasOwn(Rectangle, 'height')) // false
// console.log(Rectangle.width) // undefined
}
{
/**
* 公有实例字段:
* 公有实例字段存在于类的每一个实例中;
* 公有实例字段可以在基类的构造过程中(构造函数主体运行前)使用Object.defineProperty添加
* 也可以在子类构造函数中的super函数结束后添加
*/
class Rectangle {
width = 10
constructor () {
this.width = 20
}
}
class Cuboid extends Rectangle{
constructor() {
super()
}
}
let r = new Rectangle()
let c = new Cuboid()
// console.log(r)
// console.log(c)
}
{
class Rectangle {
width = 10
constructor () {
this.width = 20
}
output() {
return this.width
}
}
let r = new Rectangle()
// console.log(r.output()) // 20
}
{
class Rectangle {
constructor() {
console.log('r', this.width) // undefined
}
}
class Cuboid extends Rectangle {
width = 10
constructor() {
super()
console.log('c', this.width) // 10
}
}
// let c = new Cuboid()
}
{
/**
* 因为类字段是通过Object.defineProperty()添加的,
* 所以派生类中的字段声明并不会调用基类中的setter,此行为不同于在构造函数中使用this.file = ''
*/
{
class Rectangle {
set file (val) {
console.log(val)
}
}
class Cuboid extends Rectangle {
file = 10
}
let c = new Cuboid() // no log
// console.log(c)
}
{
class Rectangle {
set width(val) {
console.log(val)
}
}
class Cuboid extends Rectangle {
constructor() {
super()
this.width = 10
}
}
// let c = new Cuboid() // log 10
}
}
/**
* 公有静态方法
* 关键字static 将为一个类定义一个静态方法,静态方法不是在一个实例上被调用
* 而是在类自身之上被调用。 它们通常是工具函数,比如用来创建和复制对象
*/
{
class MyArray extends Array {
}
let arr = new MyArray(1, 2, 3, 4)
let arr2 = new Array(1, 2, 3, 4)
// console.log(arr)
// console.log(arr2)
}
/**
* 使用super调用超类
* super关键字用于调用对象的父对象上的函数
*/
{
class Cat {
constructor(name) {
this.name = name
}
speak() {
console.log(this.name + 'makes a noise')
}
}
class Lion extends Cat {
speak() {
super.speak()
console.log(this.name + 'roars.')
}
}
}
}