The “class” syntax
我們時常創造一樣的物件,像是 user、goods,建構函式可以幫我們創造一樣的物件,還有 class 結構可以幫我們。
The “class” syntax
class MyClass {
// class methods
constructor() { ... }
method1() { ... }
method2() { ... }
method3() { ... }
...
}
// example
class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi();
// new User("John") => 新的物件產生,參數被帶到 constructor
// class 不需要,
What is a class?
// class 是一種函式
class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function
// class 的方法儲存在 User.prototype
class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // alert(this.name);
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi
Not just a syntax sugar
// 不需要 class 也可以寫出一樣的功能,有人說 class 只是一種語法糖
// rewriting class User in pure functions
// 1. Create constructor function
function User(name) {
this.name = name;
}
// any function prototype has constructor property by default,
// so we don't need to create it
// 2. Add the method to prototype
User.prototype.sayHi = function() {
alert(this.name);
};
// Usage:
let user = new User("John");
user.sayHi();
// 以下有幾點跟一般函式不同
// 1. 當沒有使用 new 時 class 不能被呼叫
class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new'
// 2. class 函式用 class 開頭
class User {
constructor() {}
}
alert(User); // class User { ... }
// 3. class 方法 non-enumerable,不能顯示在迴圈 for..in
// 4. class 永遠 use strict,在 class 的程式碼都是 strict 的模式
Class Expression
// 就像一般函式,class 可以寫成 expression
let User = class {
sayHi() {
alert("Hello");
}
};
// class 的名稱可有可無
// "Named Class Expression"
// (no such term in the spec, but that's similar to Named Function Expression)
let User = class MyClass {
sayHi() {
alert(MyClass); // MyClass is visible only inside the class
}
};
new User().sayHi(); // works, shows MyClass definition
alert(MyClass); // error, MyClass not visible outside of the class
// 依照需求創造 class
function makeClass(phrase) {
// declare a class and return it
return class {
sayHi() {
alert(phrase);
};
};
}
// Create a new class
let User = makeClass("Hello");
new User().sayHi(); // Hello
Getters/setters, other shorthands
// class 也有 get/set
class User {
constructor(name) {
// invokes the setter
this.name = name;
}
get name() {
return this._name;
}
set name(value) {
if (value.length < 4) {
alert("Name is too short.");
return;
}
this._name = value;
}
}
let user = new User("John");
alert(user.name); // John
user = new User(""); // Name too short.
Object.defineProperties(User.prototype, {
name: {
get() {
return this._name
},
set(name) {
// ...
}
}
});
// 使用計算的屬性
function f() { return "sayHi"; }
class User {
[f()]() {
alert("Hello");
}
}
new User().sayHi();
Class properties
// 在 class 加屬性,並不會放到 User.prototype,該屬性是獨立的在不同物件相同 class
class User {
name = "Anonymous";
sayHi() {
alert(`Hello, ${this.name}!`);
}
}
new User().sayHi();
Last updated