Preface
å
¶å¯¦è¿å¹¾å¹´å çºå½æ¸å¼ç·¨ç¨ functional programming çèèµ·ï¼class çç¢ºå¨æ¼¸æ¼¸å¼å¾®ï¼å½æ¸å¼ç·¨ç¨é¼åµä½¿ç¨ ç´å½æ¸ (pure functions) å ä¸å¯è®æ¸æ (immutability)ï¼ç±æ¼æè®ï¼æä»¥ç¨å¼ç¢¼ææ´å®¹æè¢«çè§£ã
class Numbers {
constructor(arr) {
this.arr = arr
}
double() {
return this.arr.map(num => num * 2)
}
}
const nums = new Numbers([1, 2, 3])
console.log(nums.double()) // [2, 4, 6]
// functional programming
const doubleNumbers = arr => arr.map(num => num * 2)
console.log(doubleNumbers([1, 2, 3])) // [2, 4, 6]åè¨ä½ 乿³è¦æ¨¡çµå彿¸
class Person {
constructor(name) {
this.name = name
}
greet() {
return `Hello, my name is ${this.name}`
}
}
const createPerson = name => ({
name,
greet: () => `Hello, my name is ${name}`,
})
const person = createPerson("Jennie")
console.log(person.greet()) // Hello, my name is Jennieä½å
¶å¯¦ class ä»ç¶æå
¶æç¨å ´æ¯ï¼åæ¯ OOP (ç©ä»¶å°å) ä»ç¶å¨æäºå¤§å lib ä¸è½çå°ï¼åæ¯ Three.jsï¼åæè忝 web componentï¼ä½ éè¦ä½¿ç¨ class component extends HTMLElement {}ï¼React ä¸ç class componentâ¦çã
class
class æ¯å°åå
ç prototype é²è¡å°è£å¾çç¢ç©ï¼è® OOP çè¨è¨å¯ä»¥æ´ä½³ç´è¦ºã
function Point(x, y) {
this.x = x
this.y = y
}
Point.prototype.toString = function () {
return "(" + this.x + ", " + this.y + ")"
}
const p = new Point(1, 2)
// æ¯ä¸æ¯éåæ´æè®
class Point {
constructor(x, y) {
this.x = x
this.y = y
}
toString() {
return "(" + this.x + ", " + this.y + ")"
}
}class çæææ¹æ³é½å®ç¾©å¨ prototype 屬æ§ä¸é¢:
class Point {
constructor() {
// ...
}
toString() {
// ...
}
toValue() {
// ...
}
}
console.log(typeof Point) // "function"
console.log(Point === Point.prototype.constructor) // true
// çåæ¼
Point.prototype = {
constructor() {},
toString() {},
toValue() {},
}
// ä¹å¯ä»¥ä½¿ç¨ Object.assign() ä¾åæ·»å
Object.assign(Point.prototype, {
toString() {},
toValue() {},
})class å
§é¨å®ç¾©ç function æ¯ä¸å¯åèçï¼ç°¡å®è¬å°±æ¯ä¸è½ä½¿ç¨ Object.keys æ for...in æå°è©²å¼
// 妿æä½¿ç¨é Object.defineProperty å°±æç¥é該屬æ§
// doc: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
const person = { name: "Jennie" }
Object.defineProperty(person, "age", {
value: 18,
enumerable: false, // å°æ¤åæ¸å®ç¾©çºä¸å¯åè
})
console.log(Object.keys(person)) // ['name']
consolew.log(Object.getOwnPropertyNames(person)) // ['name', 'age']
// 使ç¨å
¶ä»æ¹æ³
console.log("age" in person) // ð¨ ééè¦æ³¨æï¼è©²æ¹æ³æå¾å° enumerableï¼æä»¥çº true
for (let x in person) {
console.log(x) // ð¨ ééè¦æ³¨æï¼è©²æ¹æ³ä¸æå¾å° enumerable ç屬æ§ï¼åªæå¾å° ['name']
}
// æåæå° class
class Point {
constructor(x, y) {
// ...
}
toString() {
// ...
}
}
console.log(Object.keys(Point.prototype)) // ç±æ¼ä¸å¯åèï¼æä»¥çº []
console.log(Object.getOwnPropertyNames(Point.prototype)) // ["constructor", "toString"]æ¯ä¸å class é è¨é½ææä¸å constructor æ¹æ³ï¼ä»æè¿å該實ä¾å°è±¡ (å³ this)ï¼æä»¥æ£å¸¸æ
æ³ä¸ new Foo() instanceof Foo æå¾å° true 使åä¹å¯ä»¥å°å
¶ä¿®æ¹è¿åå¦ä¸åå°è±¡ã
class Foo {
constructor() {
return Object.create(null)
}
}
// è¦å·è¡ class å¿
é ä½¿ç¨ new ä¾åµå»ºå¯¦ä¾
console.log(new Foo() instanceof Foo) // falseï¼åå æ¯æåå¨ constructor å
§è¿åå¦ä¸åç©ä»¶class ç屬æ§åæ¹æ³ï¼é¤éå®ç¾©å¨ this ä¸ï¼å¦å齿¯å®ç¾©å¨ class ä¸
class Point {
constructor(x, y) {
this.x = x
this.y = y
}
toString() {
return "(" + this.x + ", " + this.y + ")"
}
}
const point = new Point(2, 3)
console.log(point.toString()) // (2, 3)
console.log(point.hasOwnProperty("x")) // true
console.log(point.hasOwnProperty("y")) // true
console.log(point.hasOwnProperty("toString")) // ð¨ falseï¼æ¯ class ç屬æ§
console.log(point.__proto__.hasOwnProperty("toString")) // true
const p1 = new Point(2, 3)
const p2 = new Point(3, 2)
console.log(p1.__proto__ === p2.__proto__) // 齿¯æå class æ¬èº«æä»¥çº true
// __proto__ 䏦䏿¯èªè¨æ¬èº«çç¹æ§ï¼å¨éç¼æä¸å»ºè°ä½¿ç¨ï¼å»ºè°ä½¿ç¨ Object.getPrototypeOf()
console.log(Object.getPrototypeOf(p1) === Object.getPrototypeOf(p2)) // true
p1.__proto__.printName = function () {
return "Oops"
}
// ç±æ¼æ¯æ·»å å¨ class æä»¥ p2 ä¹å¯ä»¥å使ç¨
// ð¨ æä»¥ä½¿ç¨ __proto__ æ¹å¯« class å¿
é 謹æ
consoel.log(p1.printName()) // "Oops"
consoel.log(p2.printName()) // "Oops"ES2022 åºä¾å¾ class ç屬æ§ä¸ç¨ä¸å®è¦å¯«å¨ constructor å
§ï¼ä¹å¯ä»¥å¯«å¨æ é 層
class IncreasingCounter {
constructor() {
this._count = 0
}
get value() {
console.log("Getting the current value!")
return this._count
}
increment() {
this._count++
}
}
// ð¢ é種寫æ³çåªé»å¨æ¼ï¼ææ class é¤å±¬æ§é½å®ç¾©å¨é 層ï¼ä¸ç¼å°±è½çåºéå顿åªå¯«å±¬æ§
class IncreasingCounter {
_count = 0
constructor() {
// ...
}
get value() {
console.log("Getting the current value!")
return this._count
}
increment() {
this._count++
}
}class 乿åå¼å½æ¸ (getter) ååå¼å½æ¸ (setter)
class CustomHTMLElement {
constructor(element) {
this.element = element
}
get html() {
return this.element.innerHTML
}
set html(value) {
this.element.innerHTML = value
}
}
// åºæ¬ä¸ä½¿ç¨ä¸å°ï¼é¤éä½ ææ¯è¼è¤éç obj 仿¯ç¨ Object.definedProperty or Object.defineProperties
// Object.getOwnPropertyDescriptor æåå³
// Property Descriptor (å±¬æ§æè¿°ç¬¦) å
å«
// value - 該屬æ§ç¶åå¼
// writable (boolean) - æ¯å¦å¯ä»¥ä¿®æ¹è©²å±¬æ§
// enumerable (boolean) - æ¯å¦è½å¨ for...in æ Object.keys ä¸è¢«åè
// configurable (boolean) - æ¯å¦å¯ä»¥åªé¤è©²å±¬æ§æä¿®æ¹å®çæè¿°ç¬¦
// get (function or undefined) - è©²å±¬æ§ getter çæ¹æ³
// set (function or undefined) - è©²å±¬æ§ setter çæ¹æ³
const descriptor = Object.getOwnPropertyDescriptor(
CustomHTMLElement.prototype,
"html"
)
console.log(descriptor)
// [object Object] {
// configurable: true,
// enumerable: false,
// get: get html() {
// return this.element.innerHTML;
// },
// set: set html(value) {
// this.element.innerHTML = value;
// }
// }
console.log("get" in descriptor) // true
console.log("set" in descriptor) // trueclass ç function å稱å¯ä»¥æ¡ç¨è¡¨éå¼çæ¹å¼å¼å
¥
let methodName = "getArea"
class Square {
constructor(length) {
// ...
}
[methodName]() {
console.log("area")
}
}
const s = new Square()
s.getArea() // areaç±æ¼å¯ä»¥åæ 調æ´å稱 (Computed Property Names)ï¼ä½¿ç¨å ´æ¯æé¡ä¼¼
const lang = "es" // åè¨éæ¯ä½¿ç¨è
çèªè¨
const translations = {
en: "greet",
es: "saludar",
}
class Greeter {
[translations[lang]]() {
return lang === "es" ? "¡Hola!" : "Hello!"
}
}
const greeter = new Greeter()
// åè¨ lang è®æ enï¼å°±å¯ä»¥ä½¿ç¨ greeter.great()
console.log(greeter.saludar()) // ¡Hola!è彿¸ä¸æ¨£ï¼class ä¹å¯ä»¥ä½¿ç¨è¡¨éå¼çå½¢å¼ä¾å®ç¾©
const MyClass = class Me {
getClassName() {
return Me.name
}
}
let inst = new MyClass()
console.log(inst.getClassName()) // Me
Me.name // ReferenceError: Me is not defined
// ð¨ çºä½ inst.getClassName ææå°åº Me æ¯å çºå¨ JavaScript 䏿¯åå
·åå½å¼æ class 齿ä¸å name 屬æ§
function foo() {}
console.log(foo.name) // "foo"
class Bar {}
console.log(Bar.name) // "Bar"class å¯ä»¥ç«å³å·è¡ä¸ä¸å
·å
let person = new (class {
constructor(name) {
this.name = name
}
sayName() {
console.log(this.name)
}
})("Jennie")
person.sayName() // Jennieclass çéæ
æ¹æ³ï¼è©²æ¹æ³ä¸æè¢«å¯¦ä¾ç¹¼æ¿ï¼èæ¯ç´æ¥éé class ä¾èª¿ç¨
class Foo {
static classMethod() {
return "hello"
}
}
Foo.classMethod() // hello
const foo = new Foo()
foo.classMethod() // TypeError: foo.classMethod is not a functionstatic æç¨å ´æ¯
- éç¨å¨å·¥å ·å½å¼ï¼æç´è§çå ¶å¯¦å°±æ¯ ææ¼çµ±æ´
class MathUtils {
static add(a, b) {
return a + b
}
static subtract(a, b) {
return a - b
}
}
console.log(MathUtils.add(5, 10))
console.log(MathUtils.subtract(10, 5))- å·¥å ·å½æ¸ä¹å¯æ¯ èé¡å¥å¼·éä¿ï¼é樣使ç¨ä¸æææ´å æ¸ æ°ï¼å¦å使ç¨ç´å½å¼å°±å¥½äº
class Circle() {
constructor(radius) {
this.radius = radius
}
getArea() {
return Circle.area(this.radius)
}
static area() {
return Math.PI * radius * radius
}
}
const circle = new Circle(5)
console.log(circle.getArea())
console.log(Circle.area(10))- ç¶æç¹¼æ¿éä¿æ
class Animal {
static speak() {
return "Animals make sounds."
}
}
class Dog extends Animal {
static speak() {
return super.speak() + " Wolf!" // ä¹å¯ä»¥éé super 調ç¨
}
}
console.log(Animal.speak()) // "Animals make sounds."
console.log(Dog.speak()) // "Animals make sounds, Woof!"static ä¹å¯ä»¥ç¨å¨å±¬æ§ä¸ï¼ä¸¦å¨ class å
§ç¶ å
¨åè®æ¸ï¼ä¸ä½ç¨ç¯ååªå¨é¡å¥å
§ï¼å°¤å
¶å¨æåéç¶è·æäºè³ææ(è¨æ¸ãç·©åãè¨å®â¦ç)
class Counter {
static count = 0
static increment() {
return ++this.count
}
}
console.log(Counter.increment()) // 1
console.log(Counter.increment()) // 2
console.log(Counter.count) // 2ç§æå±¬æ§åç§ææ¹æ³ (å·éåæ¹å ä¸äºåèä¾è¡¨é #)
class IncreasingCounter {
#count = 0 // ç§æå±¬æ§
get value() {
console.log("Getting the current value!")
return this.#count
}
set value(val) {
this.#count = val
}
increment() {
this.#count++
}
}
const counter = new IncreasingCounter()
counter.#count // error
counter.#count = 42 // error
// #sum å°±æ¯ç§ææ¹æ³ï¼ä¹å¯ä»¥ç¨å¨ getter or setter ä¸
class Foo {
#a
#b
constructor(a, b) {
this.#a = a
this.#b = b
}
#sum() {
return this.#a + this.#b
}
printSum() {
console.log(this.#sum())
}
get #a() {
return this.#a;
}
}ç§æå±¬æ§åç§ææ¹æ³åä¹å¯ä»¥å ä¸é static ä¾åæé
class FakeMath {
static PI = 22 / 7
static #totallyRandomNumber = 4
static #computeRandomNumber() {
return FakeMath.#totallyRandomNumber
}
static random() {
console.log("I heard you like random numbersâ¦")
return FakeMath.#computeRandomNumber()
}
}
console.log(FakeMath.PI) // 3.142857142857143
console.log(FakeMath.random())
// I heard you like random numbersâ¦
// 4
console.log(FakeMath.#totallyRandomNumber) // error: SyntaxError: Private field....
console.log(FakeMath.#computeRandomNumber()) // error: SyntaxError: Private field...ES2020 å° in æååªåï¼ä½¿å
¶å¯ä»¥å¤æ·å°è±¡æ¯å¦æç§æå±¬æ§
class A {
#foo = 0
m() {
console.log(#foo in this) // true
}
}éæ
å±¬æ§æä¸ååé¡ï¼å¦æä»æåå§åé輯ï¼éåé輯è¦éº¼æ¯å¯«å¨ class å¤é¨ï¼è¦éº¼æ¯å¯«å¨ constructor æ¹æ³å
§ã
class C {
static x = 234
static y
static z
}
// y å z ä»°è³´ x ççµæï¼éé¨å寫å¨å¤é¨ï¼ä¸æç¶è·
// èå¾è
å¯«å¨ constructor å
§åæ¯æ¯æ¬¡æ°å»ºå¯¦ä¾æé½æéè¡ä¸æ¬¡ (å
¨åè®æ¸ä¸éè¦æ¯æ¬¡é½éè¦å¨éè¡ä¸é)
try {
const obj = doSomethingWith(C.x)
C.y = obj.y
C.z = obj.z
} catch {
// C.y = ...;
// C.z = ...;
}çºäºè§£æ±ºéååé¡ ES2020 å¼å
¥äº static blockï¼ç¶ class ç實ä¾åµå»ºå¥½å¾ï¼éå block å°±ä¸å¨éè¡äºï¼è§£æ±ºå
åå¯«å¨ constructor ç¢çéè¤éè¡çåé¡
class C {
static x = ...;
static y;
static z;
// åªæéè¡ä¸æ¬¡
// å¯ä»¥æè¤æ¸å static block
static {
try {
const obj = doSomethingWith(this.x);
this.y = obj.y;
this.z = obj.z;
// ð¨ åè¨è£¡é¢ä¸å¯æ return èªå¥
}
catch {
// this.y = ...;
// this.z = ...;
}
}
}é²éï¼é¤äºéæ
屬æ§çåå§ååè½ï¼static block éæä¸åä½ç¨ï¼å°±æ¯å°ç§æå±¬æ§è class çå¤é¨ç¨å¼ç¢¼å享
let getX
export class C {
#x = 1
static {
getX = obj => obj.#x
}
}
// 以éç¯ä¾ä¾ç obj ææ¯ C ç實ä¾ï¼æ¥èè¿å obj.#xï¼è®å¤é¨ç¨å¼ä½¿ç¨
console.log(getX(new C())) // 1ä½é樣çå¯«æ³æä½å¥½èï¼
- è®
classæ¬èº«æ²ægetX()ï¼é¿å 污æ API - è®å¤é¨è½è®åç§æå±¬æ§ï¼ä½ä¸ç´æ¥æ´é² API
- å è¨±å §é¨æ¨¡çµååï¼èéææå°æ¹
// user.js
let getSecret
export class User {
#secret = "Hidden Data"
static {
getSecret = obj => obj.#secret
}
}
export { getSecret }// main.js
import { User, getSecret } from "./user.js"
const user = new User() // User æ¬èº«ä»ä¿æå°è£æ§
console.log(getSecret(user)) // â
"Hidden Data"
console.log(user.#secret) // â SyntaxErrorNote
classå·²ç¶æ¯å´æ ¼æ¨¡å¼äºï¼æä»¥ä¸ç¨åç¹å°åuse strictclass䏿 hoist
new Foo() // ReferenceError
class Foo {}- ES6 ç
classåªæ¯å° ES5 çæ§é å½å¼å è£ï¼æä»¥è¨±å¤ç¹æ§é½è¢«ç¹¼æ¿ï¼å å« name 屬æ§
class Point {}
console.log(Point.name) // Point- Generator æ¹æ³
妿æåæ¹æ³ä¹åå 䏿èï¼*ï¼ï¼å°±è¡¨ç¤ºè©²æ¹æ³æ¯ä¸å Generator å½å¼ã
Symbol.iteratoræ¯ JavaScript ç¨ä¾å¯¦ä½è¿ä»£åå®çæ¨æºå±¬æ§- åªè¦ç©ä»¶æ
Symbol.iteratoræ¹æ³ï¼å®å°±å¯ä»¥è¢«for...ofè¿´å使ç¨
class Foo {
constructor(...args) {
this.args = args
}
*[Symbol.iterator]() {
for (let arg of this.args) {
yield arg // yield æéæ¥ç¢çä¸åå¼ï¼ç¶å¾æ«åå·è¡ï¼ç´å° for...of éè¦ä¸ä¸å弿æç¹¼çºéè¡
}
}
}
for (let x of new Foo("hello", "world")) {
console.log(x)
}
// hello
// worldthisçæå
class Logger {
printName(name = "there") {
this.print(`Hello ${name}`)
}
print(text) {
console.log(text)
}
}
const logger = new Logger()
const { printName } = logger
printName() // TypeError: Cannot read property 'print' of undefinedä¸é¢å ±é¯æ¯å çº this ææåç¶æçç°å¢ï¼ç±æ¼ class å
§é¨æ¯å´æ ¼æ¨¡å¼ï¼æä»¥ this ææå undefinedï¼é£è¦å¦ä½è§£æ±ºéååé¡
- å¯ä»¥ä½¿ç¨
bindå°thisèåµå»ºç實ä¾ç¶å®å¨ä¸èµ·- å¨å¤é 使ç¨
callå°å ¶è實ä¾ç¶å®å¨ä¸èµ·- 使ç¨ç®é å½å¼
- 使ç¨
proxy
class Logger {
constructor() {
// é裡ç bind(this) ç¢ºä¿ printName å¨è§£æ§è³¦å¼å¾ï¼ä»è½æ£ç¢ºåå Logger 實ä¾ç thisï¼ä¸æå çº this ç¶å®çåé¡å°è´é¯èª¤
this.printName = this.printName.bind(this)
}
printName(name = "there") {
this.print(`Hello ${name}`)
}
print(text) {
console.log(text)
}
}
const logger = new Logger()
const { printName } = logger
printName() // Hello thereclass Logger {
printName(name = "there") {
this.print(`Hello ${name}`)
}
print(text) {
console.log(text)
}
}
const logger = new Logger()
const { printName } = logger
printName.call(logger) // Hello there// ç®é å½å¼
class Logger {
constructor() {
// ç®é å½å¼ä¸æå»ºç«èªå·±ç thisï¼å®ç this æ°¸é æ¯å®ç¾©å®æçä½ç¨åç this
// this.printName å®ç¾©æ¼ constructorï¼æä»¥ this æ°¸é æ¯ Logger ç實ä¾
this.printName = (name = "there") => {
this.print(`Hello ${name}`)
}
}
print(text) {
console.log(text)
}
}
const { printName } = new Logger()
printName() // Hello there// ä½¿ç¨ proxy ææª Logger çååæ¹æ³ï¼ä¸¦ç¢ºä¿æææ¹æ³å¨è¢«å¼å«æï¼this é½ç¶å®å° Logger ç實ä¾ä¸
class Logger {
printName(name = "there") {
this.print(`Hello ${name}`)
}
print(text) {
console.log(text)
}
}
function selfish(target) {
const cache = new WeakMap()
const handler = {
get(target, key) {
const value = Reflect.get(target, key) // åå¾åå§å±¬æ§ææ¹æ³
if (typeof value !== "function") {
return value // éå½å¼åç´æ¥åå³
}
if (!cache.has(value)) {
cache.set(value, value.bind(target)) // ç¢ºä¿æ¹æ³ç¶å®å¨ target
}
return cache.get(value)
},
}
const proxy = new Proxy(target, handler)
return proxy
}
const logger = selfish(new Logger())
const { printName } = logger
printName()䏿¹ç°¡å®è¬ä¸ä¸çºä½ä½¿ç¨ proxy å¯ä»¥ç¯çè¨æ¶é«ï¼åå 卿¼ç¶æåµå»ºè¤æ¸åå¯¦ä¾ this.printName this.print 齿鿰åå» bind 䏿¬¡ï¼å管å¯è½å
¶ä¸çæ¹æ³å¯è½æ ¹æ¬æ²å使ç¨ã
èç±æ¼ proxy æ¯ç£æ§ï¼åªæç¶è©²æ¹æ³ç¬¬ä¸æ¬¡è¢«ååæï¼ææå·è¡ bindï¼æ¸å°ä¸å¿
è¦çå½å¼ç¢çï¼ä¸é裡ç WeakMap éå°çæ¯å½å¼ï¼è䏿¯å¯¦ä¾ï¼å æ¤å³ä½¿å»ºç«å¤å Logger 實ä¾ï¼ä»åä»å¯ä»¥å
±ç¨ printName ç bind çæ¬ã
class Logger {
constructor() {
this.printName = this.printName.bind(this) // é裡æ¯å Logger 實ä¾é½æéæ°åµå»º `printName` æ¹æ³
this.print = this.print.bind(this)
}
printName(name = "there") {
this.print(`Hello ${name}`)
}
print(text) {
console.log(text)
}
}
const logger1 = new Logger()
const logger2 = new Logger()
console.log(logger1.printName === logger2.printName) // false- new.target
å¯ä»¥ä½¿ç¨ new.target 屬æ§ï¼å¦ææ§é å½å¼ä¸æ¯éé new å½ä»¤ææ¯ Reflect.construct() 調ç¨çï¼new.target æè¿å undefined
ç°¡èè¨ä¹ Reflect.constructor(Person, [...args]) çæ¼ new Person(...args)
function Person(name) {
if (new.target !== undefined) {
this.name = name
} else {
throw new Error("å¿
é ä½¿ç¨ new å½ä»¤çæå¯¦ä¾")
}
}
// å¦ä¸ç¨®å¯«æ³
// function Person(name) {
// if (new.target === Person) {
// this.name = name
// } else {
// throw new Error("å¿
é ä½¿ç¨ new å½ä»¤çæå¯¦ä¾")
// }
// }
const person = new Person("Jennie") // good
const newParson = Reflect.construct(Person, ["Jennie"]) // good
const notAPerson = Person.call(person, "Jennie") // å¿
é ä½¿ç¨ new å½ä»¤çæå¯¦ä¾å¨ class å
§é¨èª¿ç¨ï¼è¿åç¶å Class
class Rectangle {
constructor(length, width) {
console.log(new.target === Rectangle)
this.length = length
this.width = width
}
}
const obj = new Rectangle(3, 4) // true妿æ¯ç¹¼æ¿çæ æ³ä¸ï¼æè¿ååé¡ã
class Rectangle {
constructor(length, width) {
console.log(new.target === Rectangle) // false
console.log(new.target === Square) // true
this.length = length
this.width = width
}
}
class Square extends Rectangle {
constructor(length, width) {
super(length, width)
}
}
const obj = new Square(3)ç¨éç¨®æ¹æ³å¯ä»¥è®è©² class ç¡æ³ç¨ç«ä½¿ç¨ï¼å¿
é ç¹¼æ¿å¾æå¯ä»¥ä½¿ç¨ã
class Shape {
constructor() {
if (new.target === Shape) {
throw new Error("æ¬é¡ä¸å¯å¯¦é«å")
}
}
}
class Rectangle extends Shape {
constructor(length, width) {
super()
// ...
}
}
const x = new Shape() // æ¬é¡ä¸å¯å¯¦é«å
const y = new Rectangle(3, 4) // trueConclusion
éäºæ¯æçé®ä¸å³°ä½è ECMAScript 6 å ¥é class çåºæ¬èªæ³é¨åï¼æåççè¨ï¼å¤§é¨åæ¯æ¬ç£ä¸¦å ä¸ä¸äºä½¿ç¨æ å¢åèªå·±ççè§£åæ³æ³ï¼æ¹ä¾¿èªå·±æ¥å¾æéæ±å¯ä»¥å¿«éåæ¶ã