2021 第48週 學習記錄:JavaScript Class
總結
本週集中火力閱讀 JavaScript Class 相關的內容,以下為筆記整理,基本整理自 MDN、Udemy 課程 JavaScript: Understanding the Weird Parts、YDKJS 與 JAVASCRIPT.INFO
筆記
大總結:JavaScript 的 Class 是 function constructor 的語法糖;而在 JavaScript 中使用關鍵字
new來建立新物件這件事情,本質上是「建立一個新物件,並該物件的原型([[Prototype]])指向關鍵字new後方的 function constructor 的 prototype object」
new 做的事
- Creates a blank, plain JavaScript object.
- Adds a property (
__proto__) to the new object that links to the constructor function’s prototype object. - Binds the newly created object instance as the
thiscontext (i.e. all references tothisin the constructor function now refer to the object created in the first step). - Returns
thisif the function doesn’t return an object.
以程式碼展示 constructor function’s prototype object 到底是什麼意思
- 在 UserF 中建立 method
logInfo - 設定 UserF 的 prototype 中有一 method
logInfoP - 透過 UserF 建立
jackieF與jackieF2後比較兩只物件的.logInfo與.logInfoP,發現.logInfo是位在記憶體中不同位置的兩組程式碼,而logInfoP則都指向UserF.prototype中的同一段程式碼 - 所以,當開發者想要對
jackieF或jackieF2這兩個物件使用logInfoP時,操作的其實是沿著 prototype chain 往回搜尋、找到並使用 UserF.prototype 的logInfoP
- 改為使用 class 的方式來建立並檢查兩個物件
jackie與jackie2的logInfo,也會發現logInfo其實是不是兩個jackie物件各自持有,而是兩個物件中的logInfo實際上是沿著 prototype chain 往回搜尋,並找到位於 constructor function (User) prototype object 中的logInfo
this 指向的內容
- 透過
new呼叫 function constructor 的時候,指向透過該 function constructor 新建立的物件 - function 透過
.apply()、.call()或呼叫.bind()綁定對象時,this指向那些提供給apply()、bind()或call()的物件 - 沒有透過
apply()、bind()或call(),直接經由某物件呼叫時,指向該物件(舉例:user.logInfo()是由user物件呼叫.logInfo(),this指向user) - 以上皆非,則指向
undefined(strict mode時),或指向全域物件
class 中的 static 關鍵字
MDN: Neither static methods nor static properties can be called on instances of the class. Instead, they’re called on the class itself.
MDN: Static methods are often utility functions, such as functions to create or clone objects, whereas static properties are useful for caches, fixed-configuration, or any other data you don’t need to be replicated across instances.
簡單來說就是只有 class 可以使用,而非給 class instance 操作的 properties 或 methods
class ClassWithStaticMethod {
static staticProperty = 'someValue';
static staticMethod() {
return 'static method has been called.';
}
static {
console.log('Class static initialization block called');
}
}
console.log(ClassWithStaticMethod.staticProperty);
// "someValue"
console.log(ClassWithStaticMethod.staticMethod());
// "static method has been called."
const c = new ClassWithStaticMethod();
console.log(c.staticProperty);
// undefined
console.log(c.staticMethod());
// Uncaught TypeError: c.staticMethod is not a function
如以上展示,透過 ClassWithStaticMethod 建立的 instance c 無法取得 staticProperty 的值,也無法呼叫 staticMethod()
class 中的 private 關鍵字
需注意 JavaScript 原生的 #private 與 TypeScript 的關鍵字 private 有所差異
- JavaScript
#private:- Private fields are accessible on the class constructor from inside the class declaration itself.
- It is a syntax error to refer to
#privatefrom out of scope. It is also a syntax error to refer to private fields that were not declared before they were called, or to attempt to remove declared fields withdelete.
- TypeScript keyword
private:- Doesn’t like
protected, access is NOT allowed from the member (even from subclasses). - Because private members aren’t visible to derived classes, a derived class can’t increase its visibility.
- TypeScript’s type system,
privateandprotectedare only enforced during type checking. This means that JavaScript runtime constructs likeinor simple property lookup can still access aprivateorprotectedmember. privatealso allows access using bracket notation during type checking. This makesprivate-declared fields potentially easier to access for things like unit tests, with the drawback that these fields are soft private and don’t strictly enforce privacy.
- Doesn’t like