JS Day 39: Arrow Function & this

有 N 人看过

箭頭函式 Arrow Function

如何寫箭頭函式

Function 範例:

function getProductName() {
    console.log('MacBook Pro');
};
getProductName(); // MacBook Pro

用 箭頭函式 Arrow Function 改寫:

let getProductName = () => {
    console.log('MacBook Pro');    
};
getProductName(); // MacBook Pro

如果只有一個參數傳遞進來,( ) 號可以省略。沒有任何參數時,( ) 是不可以省略的。

let sayHello = name => {
    console.log(`Hello ${name}`);
};
sayHello('George'); // Hello George

大於一個參數傳遞進來 ( ) 需要保留

let multiply = (num1, num2) => {
    return num1*num2;
};
console.log( multiply(2,3) ); // 6

上面這個例子可以再精簡。

如果函式本身不做太複雜的運算,單純要 return 一個值的話, { }return 都可以省略。

let multiply = (num1, num2) => return num1*num2; // 只剩一行
console.log( multiply(2,3) ); // 6

箭頭函式使用例子

範例1 - addEventListener:

button.addEventListener('click', function() {
    alert('Do Not Click');
});

範例1 改寫一:

button.addEventListener('click', () => {
    alert('Do Not Click');
});

範例1 改寫二:

let showAlert = () => {
    alert('Do Not Click');
};

button.addEventListener('click', showAlert);

範例2 - map:

const products = [
    {brand: 'Apple', name: 'iPhone 11 Pro', price: 800},
    {brand: 'Samsung', name: 'Galaxy S8', price: 788},
    {brand: 'Google', name: 'Pixel 4', price: 588}
];

let prices = products.map(function(item) {
    return item.price;
});

console.log(prices);

範例2 改寫:

const products = [
    {brand: 'Apple', name: 'iPhone 11 Pro', price: 800},
    {brand: 'Samsung', name: 'Galaxy S8', price: 788},
    {brand: 'Google', name: 'Pixel 4', price: 588}
];

let prices = products.map( item => item.price);

console.log(prices);

What is ‘this’?

console.log(this); // this 指向 Window

var a = 'A';
console.log(a); // A
console.log(this.a); // A
console.log(window.a); // A
console.log( this.a === window.a ); // true

目前 this 會變成 window。

function greeting() {
    console.log(this);
};
greeting(); // window

////

var name = 'Gary';
function greeting(name) {
  console.log(this.name);
};
greeting('hello'); // Gary

當下 this 還是 window 而不是 greeting() 這個函式。

this 代表的是 function 執行時所屬的物件,而不是 function 本身。 — Kuro

let getUsername = function() {
  console.log(this); // 印出 this
  return this.name;
};

const user1 = {
  id: 1,
  name: 'William',
  getUsername
};

const user2 = {
  id: 2,
  name: 'Alan',
  getUsername
};

console.log( user1.getUsername() ); // William
console.log( user2.getUsername() ); // Alan

另一個範例:

var obj = {
  func: function greeting(){
    return console.log(this);
  }
};

obj.func(); // Object { func: greeting() }

一但脫離了物件,this 的值就沒什麼意義,在沒意義的情況底下就會有個預設值,而預設值也很好記,嚴格模式就是undefined,非嚴格模式底下就是全域物件。 — Huli

console.log(this); // 非嚴格模式下就是全域物件 - window
var func = function (){
  "use strict" // 嚴格模式
  console.log(this); // undefined
};
func();

箭頭函式下的 this

將上面的範例改成 arrow function

let getUsername = () => {
    console.log(this); 
  return this.name;
};

const user1 = {
  id: 1,
  name: 'William',
  getUsername
};

const user2 = {
  id: 2,
  name: 'Alan',
  getUsername
};
console.log( user1.getUsername() ); // '' (empty string)
console.log( user2.getUsername() ); // '' (empty string)

this 指向全域物件 window

在箭頭函式下,this 會被強制綁定到其定義時所在的物件,上面的範例則是 window。

Arrow Function in Vue.js

  var app = new Vue({
    el: '#app',
    data: {
      text: '',
      newText: ''
    },
    methods: {
      reverseText: () => {
        console.log(this);
        console.log(app);
        this.newText = this.text.split('').reverse().join('');
      }
    },
  });

在 Vue.js 裡的 arrow function,this 也是指向 window

  var app = new Vue({
    el: '#app',
    data: {
      text: '',
      newText: ''
    },
    methods: {
      reverseText: function() {
        console.log(this);
        console.log(app);
        this.newText = this.text.split('').reverse().join('');
      }
    }
  });

一般 function 的 this 是指向 Vue instance, 在這個範例也就是 app.

Reference:
Arrow Function - MDN web docs
This - MDN web docs
[筆記] JavaScript ES6 中的箭頭函數(arrow function)及對 this 的影響 - PJCHENder
[筆記] 談談 JavaScript 中的 “this” 和它的問提 - PJCHENder
ECMAScript 6 入門
淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂 - TechBridge
鐵人賽:JavaScript 的 this 到底是誰? - 卡斯伯
What’s THIS in JavaScript? [上] [中] [下] - Kuro’s Blog

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。