owned this note
owned this note
Published
Linked with GitHub
###### tags: `JavaScript` `箭頭函式` `學習`
{%hackmd BJrTq20hE %}
# 甚麼是箭頭函式與箭頭函式this的指向差異
## 1-1甚麼是箭頭函式?
箭頭函式是一種新的函是寫法,與一般函式的寫法不同,有可以縮寫的優點。
範例如下
### 1-1-1一般函式
```javascript=
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箭頭函式
```javascript=
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箭頭函式的縮寫
如果函式的參數只有一個,參數()也可以省略。
加入沒有參數的話()或兩個含以上參數存在的話則()不可省略。
```javascript=
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值的時候{}也可以省略,但是要注意原本{}的內容要寫在同一行。
```javascript=
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的指向
```javascript=
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的指向
```javascript=
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指向全域
```javascript=
var name ='window';
const obj = {
name:'Jack',
callMyName: ()=>{
console.log(this.name);
},
}
obj.callMyName();//window
```
箭頭函式內的this會與外層函式的this指向相同,上面的範例中沒有外層函式,所以指向全域。
### 3-1-4外層也是箭頭函式的this的指向全域
```javascript=
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
```javascript=
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
```javascript=
var name ='window';
const obj = {
name:'Jack',
callMyName (){
setTimeout(()=>{
console.log(this.name)
})
},
}
obj.callMyName();//Jack
```
使用箭頭函式沒有this,會與(外層函式)作用域的this指向相同的特性把setTimeout內的this指向obj。
## 4-1 一般函式與箭頭函式其餘參數的差異
一般函式的其餘參數
```javascript=
function fn() {
console.log(arguments)
}
fn(1, 2, 3, 4) //Arguments(4) [1, 2, 3, 4,]
```
箭頭函式則是沒有其餘參數,會報錯。
```javascript=
const fn = () => {
console.log(arguments)
}
fn(1, 2, 3, 4) // VM1730:2 Uncaught ReferenceError: arguments is not defined
```
### 4-1-1 箭頭函式的其餘參數要怎麼寫?
```javascript=
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的指向
原始函式
```javascript=
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是指向全域,原因是箭頭函式沒有外層函數,所以會指向全域。
```javascript=
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
```
箭頭函式與一般函式放在一起看
```javascript=
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的指向 範例](https://codepen.io/efzdamnp-the-lessful/pen/VwXQyvp?editors=0011)
## 6-1 箭頭函式沒有建構函式
簡單的來說箭頭函式沒辦法透過.prototype增加方法
一般函式
```javascript=
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
```