函式
JavaScript 中的函式是一種可重複使用的程式碼,它可以接受參數並執行特定的任務。函式可以在程式中多次呼叫,這樣可以使程式更為彈性,更容易維護。
如何宣告函式
在 JavaScript 中,可以使用function
關鍵字來宣告一個函式。
以下是一個簡單的函式宣告範例:
function add(a, b) {
return a + b;
}
在此範例中,add
函式接受兩個參數,並將它們相加後返回結果。函式可以被呼叫多次,並且每次呼叫時可以傳入不同的參數值。
記憶體的變化
當函式被呼叫時,JavaScript 引擎會為該函式創建一個新的執行上下文 ( Execution Context )。該執行上下文包含函式中聲明的所有變數、參數和函式本身。當函式執行完畢並返回結果時,該執行上下文將被釋放,所有在該函式中聲明的變數和參數也將被清除。
執行上下文 ( Execution Context )
在 JavaScript 中,每當執行一個函式時,JavaScript 引擎都會創建一個新的執行上下文。
JavaScript 中的執行上下文是一種無名物件,它包含了以下三個屬性:
- Variable Object ( 變數物件 ): 儲存該執行上下文中所宣告的變數、函式和參數等。
- Scope Chain ( 作用域鏈 ): 它是用來尋找變數和函式定義的一個層層包含的列表。作用域鏈在函式被定義時就已經確定了。
- this : 它指向當前執行上下文所屬的物件。
當 JavaScript 引擎執行一段程式碼時,它會創建一個全域執行上下文 ( Global Execution Context )。在瀏覽器中,全域執行上下文通常關聯到 Window 物件。接下來,每當 JavaScript 引擎執行一個函式時,它會創建一個新的執行上下文。
以下是一個簡單的範例,說明了執行上下文如何運作:
var x = 1;
function add(y) {
var result = x + y;
return result;
}
console.log(add(2)); // 3
在此範例中,當 add
函式被呼叫時,JavaScript 引擎會創建一個新的執行上下文,其中包含了變數 y
和 result
。此外,由於 add
函式是在全域範圍內被定義的,因此它的作用域鏈會包含全域作用域鏈。
當 add
函式執行完畢並返回結果時,JavaScript 引擎會釋放該執行上下文,並將該函式的結果返回到 Call stack 中。
Call stack
JavaScript 中的呼叫堆疊(call stack)是一種用於追蹤函式執行的機制。當函式被呼叫時,它會被添加到呼叫堆疊的頂部。當函式執行完畢並返回結果時,它將從堆疊中彈出,讓下一個函式繼續執行。JavaScript 引擎使用呼叫堆疊來確保函式執行的順序和一致性。
以下是一個簡單的例子,說明了呼叫堆疊如何運作:
function fn1() {
console.log("a");
}
function fn2() {
fn1();
}
function fn3() {
fn2();
}
fn3();
在此範例中,當 fn3
函式被呼叫時,它會被添加到呼叫堆疊的頂部。當 fn3
函式調用 fn2
函式時, fn2
函式被添加到堆疊的頂部。當 fn2
函式調用 fn1
函式時, fn1
函式被添加到堆疊的頂部。當 fn1
函式執行完畢時,它從堆疊中彈出,讓 fn2
函式繼續執行。當 fn2
函式執行完畢時,它從堆疊中彈出,讓 fn3
函式繼續執行。最後,當 fn3
函式執行完畢時,它從堆疊中彈出,函式呼叫堆疊就空了。
以下是一個動畫,說明了呼叫堆疊如何運作:
圖片來源:https://vaibhavgupta.me/2018/01/20/understanding-event-loop/
this 是什麼
在 JavaScript 中,this
關鍵字用於引用當前執行上下文中的物件。this
關鍵字的值取決於函式的調用方式,它可以是全域物件、函式本身或由該函式創建的新物件。
當在全域範圍內使用 this
*時,它會指向全域物件 (在瀏覽器中是 Window
*)。
以下是一個範例:
console.log(this); // Window
以下是一個簡單的範例,其中 this
關鍵字用於引用當前執行上下文中的物件:
const person = {
firstName: 'John',
lastName: 'Doe',
fullName: function() {
return `${this.firstName} ${this.lastName}`;
}
}
console.log(person.fullName()); // "John Doe"
在此範例中,this
關鍵字用於引用 person
物件,因為函式是在 person
物件上調用的。
🔑 一般的函式呼叫 JS 會預設將 this 綁定到全域物件,當從某個物件的參考屬性呼叫 this 會綁定到該物件
let obj = {
function1: function() {
console.log(this); // obj
let function2 = function() {
console.log(this); // Window
}
function2();
}
};
obj.function1();
當使用 call()
、apply()
****或 bind()
方法時,可以手動指定 this
的值。
以下是一個範例:
const person1 = {
firstName: 'John',
lastName: 'Doe'
}
const person2 = {
firstName: 'Jane',
lastName: 'Don'
}
function fullName() {
return `${this.firstName} ${this.lastName}`;
}
console.log(fullName.call(person1)); // "John Doe"
console.log(fullName.call(person2)); // "Jane Don"
💡 call()
、apply()
、bind()
的不同
-
call()
、apply()
會立即執行函式,bind()
會回傳一個新的函式 -
call(thisArg[, arg1[, ...]])
****是列出所有參數,apply(thisArg, [argsArray])
是傳入陣列
在使用 new
*關鍵字創建一個物件時,this
*會指向這個新物件。
以下是一個範例:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = function() {
return `${this.firstName} ${this.lastName}`;
}
}
const john = new Person('John', 'Doe');
console.log(john.fullName()); // "John Doe"
箭頭函式 ( Arrow Function )
在 ES6 中,引入了箭頭函式的概念。箭頭函式是一種更簡潔的函式語法,它使用 =>
符號來定義函式。箭頭函式有一些特別的行為:
- 箭頭函式沒有自己的
this
關鍵字,它繼承了外部執行上下文的this
值。 - 箭頭函式總是匿名的,因此不能使用
function
關鍵字來命名箭頭函式。 - 箭頭函式的
return
關鍵字是隱式的,因此不需要顯式地返回值。
以下是一個使用箭頭函式的簡單範例:
const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = numbers.map(number => number * 2);
console.log(doubledNumbers); // [2, 4, 6, 8, 10]
在此範例中,箭頭函式被用於將 numbers
數組中的每個數字乘以 2。這個函式使用了箭頭函式簡潔的語法,並返回一個新的數組。
Top comments (0)