延續昨天的話題,今天舉了一些例子來說明實際上可能的應用場景。
如何避免呼叫一般函式時,其中的this是undefined的問題,最好的方法就是不要呼叫一般的函式,因為最好的進攻就是防守,解決問題不如解決提出問題的人但作為一個天天照三餐呼叫一般函式的程式小白,這境界好像離我有點遠。
我現在會作的是使用call() & bind()手動地指定this指向誰,下面舉兩個例子說明,一個是單純的simple function call,另一個是建構函式(constructor)串接,也就是一個建構函式要參照另一個建構函式時的作法。
第一個例子我們寫了一個含有this的一般函式
const calcAge = function () {
return 2023 - this.birthYear;
};
const john = {
firstName: "John",
birthYear: 1990,
};
const age = calcAge(); //simple function call
console.log(age); //報錯, Cannot read properties of undefined (reading 'birthYear')
const age2 = calcAge.call(john); //use call() 指定this指向物件john
console.log(age); //33
再來比較實際的使用是作在建構函式的互相參照,像下面的例子,Person是perant class,Student是想要參照Person的child class,我們如果直接在Student建構函式當中呼叫Person,因為把Person視為函式,這樣會變成simple function call,為了重新指定this,我們使用call()把Person裡的this,指向後來利用Student建立的新物件。
const Person = function (firstName, birthYear) {
this.firstName = firstName;
this.birthYear = birthYear;
};
const Student = function (firstName, birthYear, studying) {
Person.call(this, firstName, birthYear);
this.studying = studying;
};
const mark = new Person("Mark", 2000);
console.log(mark);
const peter = new Student("Peter", 2005, "Computer scinece");
console.log(peter);
在昨天的event listener的例子中,因為this指向監聽元素本身而造成bug,但若使用arrow function則可以輕巧簡單的避開這個問題。從執行結果可以發現,在event listener的calll back funct6ion改用arrow function之後,當中的this抓到的是外面一層也就是greet method的this:物件john。
const john = {
firstName: "John",
greet: function () {
const btnEl = document.querySelector("button");
btnEl.addEventListener("click", () => {
console.log(this);
alert(`Hi, I'm ${this.firstName}.`);
});
},
};
執行結果:
熟悉this的幾個規則,就可以輕鬆面對各種this的應用變化,這跟本系列主題超低腦容量學習法根本超級切題的,我最喜歡這種了!