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
主题 StackJimmy 设计