iT邦幫忙

2022 iThome 鐵人賽

DAY 23
0
自我挑戰組

JavaScript101與人生幹話系列 第 23

JavaScript101與人生幹話-箭頭函式與箭頭函式的this

  • 分享至 

  • xImage
  •  

1-1甚麼是箭頭函式?

箭頭函式是一種新的函是寫法,與一般函式的寫法不同,有可以縮寫的優點。
範例如下

1-1-1一般函式

let arr = [1,2,3,4,5];
let newarr = arr.map(function(item){
  return  item*2
});
console.log(newarr);//[2,4,6,8,10]

1-1-2箭頭函式

let arr = [1,2,3,4,5];
let newarr = arr.map((item)=>{
  return  item*2
});
console.log(newarr);//[2,4,6,8,10]

可以發現把function移除,然後在()後加上=>

2-1箭頭函式的縮寫

如果函式的參數只有一個,參數()也可以省略。
加入沒有參數的話()或兩個含以上參數存在的話則()不可省略。

let arr = [1,2,3,4,5];
let newarr = arr.map(item=>{
  return  item*2
});
console.log(newarr);//[2,4,6,8,10]

2-2箭頭函式的縮寫2

函式需要return值的時候{}也可以省略,但是要注意原本{}的內容要寫在同一行。

let arr = [1,2,3,4,5];
let newarr = arr.map(item=>item*2);
console.log(newarr);//[2,4,6,8,10]

3-1箭頭函式沒有自己的this

原函式寫法this的指向

var name ='window';
const obj = {
    name:'Jack',
    callMyName (){
        console.log(this.name+' this指向obj');
        // 因為在callback function 內的this都指向全域。
        setTimeout(function(){
            console.log(this.name+' this指向window')
        })
    },
}
obj.callMyName();//Jack this指向obj  window this指向window

從上面的例子可以看到callMyName()是從obj內調用的所以this指向obj,而setTimeout這個callback function是一種simple call 可以想成setTimeout()是放在window裡所以setTimeout()的this會指向window。

3-1-1 箭頭函式this的指向

var name ='window';
const obj = {
    name:'Jack',
    callMyName (){
        console.log(this.name+'1');
        setTimeout(()=>{
            console.log(this.name+'2')
        })
    },
    
}
obj.callMyName();//Jack1  Jack2

把setTimeout內的函是改寫為箭頭函式,因為箭頭函式沒有自己的this,所以在箭頭含式內的this會指向外層函式的作用域的this,外層函式為傳統函式所以this的指向與如何調用函是相關。

3-1-3沒有外層函式的的箭頭函式的this指向全域

var name ='window';
const obj = {
    name:'Jack',
    callMyName: ()=>{
        console.log(this.name);
    },
    
}
obj.callMyName();//window

箭頭函式內的this會與外層函式的this指向相同,上面的範例中沒有外層函式,所以指向全域。

3-1-4外層也是箭頭函式的this的指向全域

var name ='window';
const obj = {
    name:'Jack',
    callMyName: ()=>{
        console.log(this.name+'1');
        setTimeout(()=>{
            console.log(this.name+'2')
        })
    },
}
obj.callMyName();//window1  window2

因為setTimeout外層函數也是箭頭函式,所以this的指向看外層函式,又因為外層函式是箭頭函式且沒有更外層的函式所以所有的this都指向window。

3-1-5確定this的指向-方法1

var name ='window';
const obj = {
    name:'Jack',
    callMyName (){
        let vm = this;
        setTimeout(function(){
            console.log(vm.name)
        })
    },
    
}
obj.callMyName();//Jack

在callback function同層宣告變數vm=this;改變this的指向

3-1-5確定this的指向-方法2

var name ='window';
const obj = {
    name:'Jack',
    callMyName (){
        setTimeout(()=>{
            console.log(this.name)
        })
    },
    
}
obj.callMyName();//Jack

使用箭頭函式沒有this,會與(外層函式)作用域的this指向相同的特性把setTimeout內的this指向obj。

4-1 一般函式與箭頭函式其餘參數的差異

一般函式的其餘參數

function fn() {
    console.log(arguments)
}
fn(1, 2, 3, 4) //Arguments(4) [1, 2, 3, 4,]

箭頭函式則是沒有其餘參數,會報錯。

const fn = () => {
    console.log(arguments)
}
fn(1, 2, 3, 4) // VM1730:2 Uncaught ReferenceError: arguments is not defined

4-1-1 箭頭函式的其餘參數要怎麼寫?

const fn = (par, ...pars) => {
    console.log(par)
    console.log('其餘參數',...pars)
    const value = Object.values(pars)
    console.log('取出其餘物件', value)
}
fn(1, 'a', 'b', 5, 6)// 1   '其餘參數'  a b 5 6
// ['a', 'b', '5', '6']

5-1 箭頭函式與call()、apply()、bind()對於this的指向

原始函式

var name = '123'
const obj = {
    name: 'Jack'
}
const fn1 = function(par1, par2) {
    console.log(this.name, par1, par2)
}
fn1.call(obj, 'May', 'John') // Jack May John

箭頭函式
可以看到使用Call但試箭頭函式內的this是指向全域,原因是箭頭函式沒有外層函數,所以會指向全域。

var name = '123'
const obj = {
    name: 'Jack'
}
const fn1 = (par1, par2) => {
    console.log(this.name, par1, par2)
}
fn1.call(obj, 'May', 'John') // 123 May John

箭頭函式與一般函式放在一起看

var name = '123'
const obj = {
    name: 'Jack',
    fn1: (par1, par2) => {
    console.log('fn1',this.name, par1, par2)
    },
    fn2:function(par1, par2) {
      console.log('fn2',this.name, par1, par2)
    },
    fn3:function(par1, par2) {
      setTimeout(()=>{
        console.log('fn3',this.name, par1, par2) 
      })
    },
    fn4:(par1, par2) => {
      setTimeout(()=>{
        console.log('fn4',this.name, par1, par2) 
      })
    }
}
//雖然call有定義this指向但是在箭頭函式內的this的指向還是由外層函數的this指向為主,如果沒有外層函式則指向全域。
obj.fn1.call(obj, 'May', 'John') // 123 May John
obj.fn2.call(obj, 'May', 'John') // Jack May John
obj.fn3.call(obj, 'May', 'John') // Jack May John
obj.fn4.call(obj, 'May', 'John') // 123 May John

箭頭函式、call this的指向 範例

6-1 箭頭函式沒有建構函式

簡單的來說箭頭函式沒辦法透過.prototype增加方法
一般函式

const List = function(name){
    this.name = name
}
const List2 = (name)=> {
    this.name = name
}
console.log(List.prototype, List2.prototype) //{constructor: ƒ} undefined

const list = new List('Jack') 
console.log(list) // List {name: 'Jack'}
const list2 = new List2('Jack') // Uncaught TypeError: List2 is not a constructor

人生幹話-晚二十年出生

那個第三點就是,對基層員工十分小氣,布告欄上寫到某某作業員發現製成能改善的地點,並提出改善方法,並經過驗證後方法可行,可幫公司每年省下200萬元,記嘉獎一支,獎金2000以玆鼓勵,希望各位同仁能夠效法,看到上面這一段我懷疑我是不是看錯了獎金,這種廢到笑的獎勵如果是各位還會為這家公司拚全力呢?我是不會啦,反正幫公司年省200萬我也只拿一次2000,相對的跟隨老闆創業的老屁股要離開公司的時候,老闆還會擔心老屁股沒錢,還特別用顧問的方式資助而且每個月只要到公司一次就行,據說顧問費家車馬費是每個月6-10萬,只能說出生的太晚。


上一篇
JavaScript101與人生幹話-this的範例
下一篇
JavaScript101與人生幹話-執行環境、作用域
系列文
JavaScript101與人生幹話30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言