Featured image of post 【JavaScript 變數】變數類型介紹:函式 Function、箭頭函式

【JavaScript 變數】變數類型介紹:函式 Function、箭頭函式

【JavaScript 變數】變數類型介紹:函式 Function、箭頭函式

Photo by Mohammad Rahmani on Unsplash

函式方法

變數 說明
Function.call() 執行函式,並改變函式中的 this 物件為指定變數,函式參數依序帶入
Function.apply() 執行函式,並改變函式中的 this 物件為指定變數,函式參數為陣列
Function.bind() 建立函式,並改變函式中的 this 物件為指定變數,下次呼叫時會使用改變過後的 this 物件執行

綁定 this 方式

  • callapply 皆是直接執行函式,只是參數傳入方式不同
  • bind 會綁定 this 並回傳已綁定函式,在之後呼叫執行

function add(a, b) {
  return a + b;
}
// call
console.log(add.call(null, 1, 2));		// 3
console.log(add.call(null, 1, 4));		// 5

// apply
console.log(add.apply(null, [1, 2]));	// 3
console.log(add.apply(null, [1, 4]));	// 5

// bind
let add1 = add.bind(null, 1);
console.log(add1(2));			            // 3
console.log(add1(4));			            // 5

call

傳入參數第一個是要改變的 this 變數,後面是函式需要用的參數,依序列出

Function.call(要改變的this, 參數1, 參數2...)

apply

傳入參數只有 2 個,函式用的參數用陣列包起來傳入

Function.apply(要改變的this, [參數1, 參數2...])

bind

Function.bind(要改變的this, 參數1, 參數2...)

函式預設值

在傳入參數後方加入 = 即可設定預設值

const SayHi = (name, age = 17) => {
    console.log(`My name is "${name}", and my age is "${age}"`);
}

// My name is "Kay", and my age is "19"
SayHi('Kay', 19);
// My name is "Jay", and my age is "17"
SayHi('Jay');

舊的設定預設值方式

const SayHi = (name, age ) => {
    age = age || 17;
    console.log(`My name is "${name}", and my age is "${age}"`);
}

// My name is "Kay", and my age is "19"
SayHi('Kay', 19);
// My name is "Jay", and my age is "17"
SayHi('Jay');

使用 new 建立 Function 實例

new 會讓 this 指向到新建立的物件實體

function Animal(name) {
    this.name = name;
    this.walk = () => {
        console.log(`[Animal] ${this.name} walking`);
    }
}

let myAnimal = new Animal('Kay');

// Animal { name: 'Kay', walk: [Function (anonymous)] }
console.log(myAnimal);

用函式縮寫的方式沒辦法順利 new 物件實例

let Animal = (name) => {
    this.name = name;
    this.walk = () => {
        console.log(`[Animal] ${this.name} walking`);
    }
}

// TypeError: Animal is not a constructor
let myAnimal = new Animal('Kay');

原始函式與箭頭函式比較

原始函式

function greeting() {
  console.log('Hello, JavaScript!!');
}

greeting();

箭頭函式

const greeting = () => {
  console.log('Hello, JavaScript!!');
};

greeting();

函式僅回傳指定資料

函式本身只是要回傳某個值的話,可以把 return 這個字省略掉,要回傳的資料直接放在箭頭後方

const greeting = () => console.log('Hello, JavaScript!!');
greeting();
const greeting = () => 'Hello, JavaScript!!';
console.log(greeting()); // 'Hello, JavaScript!!'

// 等同於這樣寫
const greeting = function () {
  return 'Hello, JavaScript!!';
};

箭頭函式帶入參數值

const add = (a, b) => a + b;
console.log(add(3, 5));

// 等同於這樣寫
const add = function (a, b) {
  return a + b;
};

箭頭函式對 this 的影響

箭頭函式當中的 this 綁定的是是定義時的物件,而不是使用時的物件,所以定義當下 this 指的是哪個物件就會是那個物件,不會隨著時間改變

let id = 21;
let data = {
    id: 21,
};

fn.call(data);
arrowFn.call(data);

// 原本的 function
function fn() {
    // [fn] Object
    console.log(`[fn] ${this.constructor.name}`);

    setTimeout(function () {
        // [fn.setTimeout] Timeout
        console.log(`[fn.setTimeout] ${this.constructor.name}`);
    }, 100);
}

// 箭頭函式 Arrow function
function arrowFn() {
    // [arrowFn] Object
    console.log(`[arrowFn] ${this.constructor.name}`);

    setTimeout(() => {
        // [arrowFn.setTimeout] Object
        console.log(`[arrowFn.setTimeout] ${this.constructor.name}`);
    }, 100);
}
  • this.constructor.name:這樣子的寫法只是避免在回傳出物件的時候,把整個物件內容給傳出來,而是僅傳出該物件的名稱。

使用 .call(data) 指定在函式都是使用 data 這個物件當作是 this 物件

fn.call(data) 傳統函式

裡面的 setTimeout 執行的時間點是在 Stack 沒有任務時,才從 task queue 拿出來執行,當時的執行環境是 global environment,所以 this 的綁定會依據當時執行的環境換掉

arrowFn.call(data) 箭頭函式

裡面的 setTimeout 是在 data 物件當成是 this 時候定義的,所以箭頭函式內的 this 會一直綁定為原呼叫的物件

參考資料

Donate KJ 贊助作者喝咖啡

如果這篇文章對你有幫助的話,可以透過下面支付方式贊助作者喝咖啡,如果有什麼建議或想說的話可以贊助並留言給我
If this article has been helpful to you, you can support the author by treating them to a coffee through the payment options below. If you have any suggestions or comments, feel free to sponsor and leave a message for me!
方式 Method 贊助 Donate
PayPal https://paypal.me/kejyun
綠界 ECPay https://p.ecpay.com.tw/AC218F1
歐付寶 OPay https://payment.opay.tw/Broadcaster/Donate/BD2BD896029F2155041C8C8FAED3A6F8
All rights reserved,未經允許不得隨意轉載
Built with Hugo
Theme Stack designed by Jimmy